home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / fs / fsStubs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  107.3 KB  |  4,301 lines

  1. /* 
  2.  * fsStubs.c --
  3.  *
  4.  *    Stubs for Unix compatible system calls.
  5.  *
  6.  * Copyright 1990 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fs/fsStubs.c,v 1.19 92/06/01 14:47:19 kupfer Exp $";
  18. #endif /* not lint */
  19.  
  20. #define MACH_UNIX_COMPAT
  21.  
  22. #include <sprite.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <status.h>
  27. #include <errno.h>
  28. #include <assert.h>
  29. #include <fsprefix.h>
  30. #include <user/sys/types.h>
  31. #include <user/sys/file.h>
  32. #include <user/sys/wait.h>
  33. #include <user/sys/time.h>
  34. #include <user/sys/resource.h>
  35. #include <user/sys/stat.h>
  36. #include <user/sys/uio.h>
  37. #include <user/sys/ioctl.h>
  38. #include <user/sys/termio.h>
  39. #include <user/sys/termios.h>
  40. #include <user/sys/dir.h>
  41. #include <user/sys/dirent.h>
  42. #include <user/dev/tty.h>
  43. #include <user/dev/net.h>
  44. #include <user/dev/graphics.h>
  45. #include <user/bit.h>
  46. #include <user/fcntl.h>
  47. #include <mach.h>
  48. #include <proc.h>
  49. #include <vm.h>
  50. #include <fs.h>
  51. #include <fsUnixStubs.h>
  52. #include <procUnixStubs.h>
  53. #include <fsutil.h>
  54. #include <fsio.h>
  55. #include <fslcl.h>
  56. #include <user/inet.h>
  57.  
  58. static char *errs[] = {"ENOERR", "EPERM", "ENOENT", "ESRCH", "EINTR", "EIO",
  59.     "ENXIO", "E2BIG", "ENOEXEC", "EBADF", "ECHILD", "EAGAIN", "ENOMEM",
  60.     "EACCES", "EFAULT", "ENOTBLK", "EBUSY", "EEXIST", "EXDEV", "ENODEV",
  61.     "ENOTDIR", "EISDIR", "EINVAL", "ENFILE", "EMFILE", "ENOTTY",
  62.     "ETXTBSY", "EFBIG", "ENOSPC", "ESPIPE", "EROFS", "EMLINK", "EPIPE",
  63.     "EDOM", "ERANGE", "EWOULDBLOCK", "EINPROGRESS", "EALREADY", "ENOTSOCK",
  64.     "EDESTADDRREQ", "EMSGSIZE", "EPROTOTYPE", "ENOPROTOOPT",
  65.     "EPROTONOSUPPORT", "ESOCKTNOSUPPORT", "EOPNOTSUPP", "EPFNOSUPPORT",
  66.     "EAFNOSUPPORT", "EADDRINUSE", "EADDRNOTAVAIL", "ENETDOWN",
  67.     "ENETUNREACH", "ENETRESET", "ECONNABORTED", "ECONNRESET", "ENOBUFS",
  68.     "EISCONN", "ENOTCONN", "ESHUTDOWN", "ETIMEDOUT", "ECONNREFUSED",
  69.     "ELOOP", "ENAMETOOLONG", "EHOSTDOWN", "EHOSTUNREACH", "ENOTEMPTY",
  70.     "EPROCLIM", "EUSERS", "EDQUOT", "ESTALE", "EREMOTE"};
  71.  
  72. #undef Mach_SetErrno
  73. #define Mach_SetErrno(err) if (debugFsStubs) { \
  74.     printf("Error %d (%s) at %d in %s\n", err,\
  75.     err<sizeof(errs)/sizeof(char *)?errs[err]:"",\
  76.     __LINE__, __FILE__); } Proc_GetActualProc()->unixErrno = (err)
  77.  
  78. /*
  79.  * The following defines are flags that are defined differently in
  80.  * termios.h (T_) and ioctl.h (I_).
  81.  * We define them uniquely here, so we don't get messed up.
  82.  */
  83. #define T_NL1    0x00000100
  84. #define I_NL1    0x00000100
  85. #define I_NL2    0x00000200
  86. #define I_CR0    0x00000000
  87. #define T_CR1    0x00000200
  88. #define I_CR1    0x00001000
  89. #define T_CR2    0x00000400
  90. #define I_CR2    0x00002000
  91. #define T_CR3    0x00000600
  92. #define I_CR3    0x00003000
  93. #define T_TAB1    0x00000800
  94. #define I_TAB1    0x00000400
  95. #define T_TAB2    0x00001000
  96. #define I_TAB2    0x00000800
  97. #define T_NOFLSH    0x00000080
  98. #define I_NOFLSH    0x80000000
  99. #define T_TOSTOP    0x00000100
  100. #define I_TOSTOP    0x00400000
  101. #define T_FLUSHO    0x00002000
  102. #define I_FLUSHO    0x00800000
  103.  
  104. /*
  105.  * Select defines from mach/ds3100.md/socket.h
  106.  */
  107. #define MAX_NUM_STREAMS        1024
  108. #define BITS_PER_ROW        32
  109. #define MAX_NUM_ROWS        (MAX_NUM_STREAMS/BITS_PER_ROW)
  110.  
  111. #ifndef Mach_SetErrno
  112. #define Mach_SetErrno(err)
  113. #endif
  114.  
  115. int debugFsStubs = 0;
  116.  
  117. static int CvtSpriteToUnixType _ARGS_((register int spriteFileType));
  118. static void CvtSpriteToUnixAtts _ARGS_((register Fs_Attributes *spriteAttsPtr,
  119.     register struct stat *unixAttsPtr));
  120. static void CvtTermiosToSgttyb _ARGS_((int termiosFlag, struct termios *ts,
  121.     struct sgttyb *ttyb, unsigned int *lmode, struct tchars *tc,
  122.     struct ltchars *ltc));
  123. static void CvtSgttybToTermios _ARGS_((struct sgttyb *ttyb,
  124.     unsigned int *lmode, struct tchars *tc, struct ltchars *ltc,
  125.     struct termios *ts));
  126. static int GetTermInfo _ARGS_ ((Fs_Stream *streamPtr, Fs_IOCParam *ioctl,
  127.     struct sgttyb *ttyb, unsigned int *lmode, struct tchars *tc,
  128.     struct ltchars *ltc));
  129. extern int CheckIfPresent _ARGS_((char *name));
  130. static char *copyin _ARGS_((char *string));
  131. static int Fs_GetdirInt _ARGS_((int fd, int nbytes, Address buf, long *off));
  132.  
  133. /*
  134.  *----------------------------------------------------------------------
  135.  *
  136.  * CvtSpriteToUnixType --
  137.  *
  138.  *    Convert from Sprite file types to the IFMT mode bits of a unix file
  139.  *
  140.  * Results:
  141.  *    Unix file type bits.
  142.  *
  143.  * Side effects:
  144.  *     none.
  145.  *
  146.  *----------------------------------------------------------------------
  147.  */
  148. static int
  149. CvtSpriteToUnixType(spriteFileType)
  150.     register    int spriteFileType;
  151. {
  152.     register unixModeBits;
  153.  
  154.     switch (spriteFileType) {
  155.     default:
  156.     case FS_FILE:
  157.         unixModeBits = S_IFREG;
  158.         break;
  159.     case FS_DIRECTORY:
  160.         unixModeBits = S_IFDIR;
  161.         break;
  162.     case FS_SYMBOLIC_LINK:
  163.         unixModeBits = S_IFLNK;
  164.         break;
  165.     case FS_DEVICE:
  166.     case FS_REMOTE_DEVICE:        /* not used */
  167.         unixModeBits = S_IFCHR;
  168.         break;
  169.     case FS_LOCAL_PIPE:        /* not used */
  170.     case FS_NAMED_PIPE:
  171.         unixModeBits = S_IFIFO;
  172.         break;
  173.     case FS_REMOTE_LINK:
  174.         unixModeBits = S_IFLNK;    /* a lie */
  175.         break;
  176.     case FS_PSEUDO_DEV:
  177.         unixModeBits = S_IFCHR;    /* another lie */
  178.         break;
  179.     }
  180.     return(unixModeBits);
  181. }
  182.  
  183. /*
  184.  *----------------------------------------------------------------------
  185.  *
  186.  * CvtSpriteToUnixAtts --
  187.  *
  188.  *    Procedure to convert the Sprite file system attributes 
  189.  *    structure to the Unix format.
  190.  *
  191.  * Results:
  192.  *    none.
  193.  *
  194.  * Side effects:
  195.  *     none.
  196.  *
  197.  *----------------------------------------------------------------------
  198.  */
  199. static void
  200. CvtSpriteToUnixAtts(spriteAttsPtr, unixAttsPtr)
  201.     register    struct stat    *unixAttsPtr;
  202.     register    Fs_Attributes    *spriteAttsPtr;
  203. {
  204.     unixAttsPtr->st_dev        = spriteAttsPtr->domain;
  205.     unixAttsPtr->st_ino        = spriteAttsPtr->fileNumber;
  206.     unixAttsPtr->st_mode    = (spriteAttsPtr->permissions & 0xfff) |
  207.                     CvtSpriteToUnixType(spriteAttsPtr->type);
  208.     unixAttsPtr->st_nlink    = spriteAttsPtr->numLinks;
  209.     unixAttsPtr->st_uid        = spriteAttsPtr->uid;
  210.     unixAttsPtr->st_gid        = spriteAttsPtr->gid;
  211.     unixAttsPtr->st_rdev    = (spriteAttsPtr->devType << 8) |
  212.                   (spriteAttsPtr->devUnit & 0xff);
  213.     unixAttsPtr->st_size    = spriteAttsPtr->size;
  214.     unixAttsPtr->st_blksize    = spriteAttsPtr->blockSize;
  215.     unixAttsPtr->st_blocks    = spriteAttsPtr->blocks * 2;
  216.     unixAttsPtr->st_atime    = spriteAttsPtr->accessTime.seconds;
  217.     unixAttsPtr->st_spare1    = 0;
  218.     unixAttsPtr->st_mtime    = spriteAttsPtr->dataModifyTime.seconds;
  219.     unixAttsPtr->st_spare2    = 0;
  220.     unixAttsPtr->st_ctime    = spriteAttsPtr->descModifyTime.seconds;
  221.     unixAttsPtr->st_spare3    = 0;
  222.     /*
  223.      * The Unix stat structure is 8 bytes shorter than we declare it in
  224.      * sys/stat.h.  The Unix stat structure has 2 unused words on the
  225.      * end.
  226.      */
  227.     unixAttsPtr->st_serverID    = 0;
  228.     unixAttsPtr->st_version    = 0;
  229.     /*
  230.     unixAttsPtr->st_serverID    = spriteAttsPtr->serverID;
  231.     unixAttsPtr->st_version    = spriteAttsPtr->version;
  232.     unixAttsPtr->st_userType    = spriteAttsPtr->userType;
  233.     unixAttsPtr->st_devServerID = spriteAttsPtr->devServerID;
  234.     */
  235.     return;
  236. }
  237.  
  238.  
  239. /*
  240.  *----------------------------------------------------------------------
  241.  *
  242.  * CvtTermiosToSgttyb --
  243.  *
  244.  *    Convert from termios structure to sgttyb structure.
  245.  *    Note: ttyb, lmode, tc, and ltc must be initialized on entry.
  246.  *    This routine is carefully set up to match the behavior
  247.  *    of SunOS for all input combinations.  As a result, this
  248.  *    routine is not intuitive.  It's probably best not to
  249.  *    change this routine unless you have a good reason.
  250.  *    Then again, there's a good chance I got something wrong.
  251.  *
  252.  * Results:
  253.  *    None.
  254.  *
  255.  * Side effects:
  256.  *    Changes ttyb, lmode, tc, ltc.
  257.  *
  258.  *----------------------------------------------------------------------
  259.  */
  260. static void
  261. CvtTermiosToSgttyb(termiosFlag, ts, ttyb, lmode, tc, ltc)
  262.     int termiosFlag;        /* 1 if termios, 0 if termio. */
  263.     struct termios *ts;        /* In */
  264.     struct sgttyb *ttyb;    /* In, out */
  265.     unsigned int *lmode;    /* In, out */
  266.     struct tchars *tc;        /* In, out */
  267.     struct ltchars *ltc;    /* In, out */
  268. {
  269.     unsigned int flag, iflag, oflag, lflag, cflag;
  270.  
  271.     iflag = ts->c_iflag;
  272.     oflag = ts->c_oflag;
  273.     lflag = ts->c_lflag;
  274.     cflag = ts->c_cflag;
  275.  
  276.     flag = EVENP|ODDP|CBREAK;
  277.  
  278.     if (!(cflag&PARENB)&&(cflag&CSIZE)==CS8) {
  279.     flag &= ~(ODDP|EVENP|PASS8);
  280.     flag |= ttyb->sg_flags & (ODDP|EVENP);
  281.     if (*lmode&(PASS8>>16)) { flag |= PASS8; }
  282.     if (!(oflag&OPOST)) { flag |= LITOUT; }
  283.     if (!(iflag&ISTRIP)&&(oflag&OPOST)) { flag |= PASS8; }
  284.     } else {
  285.     if (cflag&PARODD) { flag &= ~EVENP; }
  286.     if ((iflag&INPCK)&&!(cflag&PARODD)) { flag &= ~ODDP; }
  287.     }
  288.  
  289.     if (!(iflag&IXANY)) { flag |= DECCTQ; }
  290.     if (iflag&IXOFF) { flag |= TANDEM; }
  291.  
  292.  
  293.     if (oflag&OLCUC) { flag |= LCASE; }
  294.     if (oflag&ONLCR) {
  295.     flag |= CRMOD;
  296.     if ((oflag&CRDLY)==T_CR2) {
  297.         flag |= I_CR1;
  298.     } else if ((oflag&CRDLY)==T_CR3) {
  299.         flag |= I_CR2;
  300.     }
  301.     }
  302.     if (oflag&ONLRET) {
  303.     if ((oflag&NLDLY)==T_NL1) { flag |= I_NL2; }
  304.     if (!(oflag&ONLCR) && (oflag&T_CR1)) {
  305.         flag |= I_NL1;
  306.     }
  307.     }
  308.     if (oflag&T_TAB1) { flag |= I_TAB1; }
  309.     if (oflag&T_TAB2) { flag |= I_TAB2; }
  310.     if (oflag&BSDLY) { flag |= BSDELAY; }
  311.     if (oflag&FFDLY) { flag |= VTDELAY; }
  312.  
  313.     if (cflag&CLOCAL) { flag |= NOHANG; }
  314.  
  315.     if (lflag&ICANON) { flag &= ~CBREAK; }
  316.     if (lflag&ECHOE) { flag |= CRTERA|CRTBS; }
  317.     if (lflag&T_NOFLSH) { flag |= I_NOFLSH; }
  318.     if (lflag&T_TOSTOP) { flag |= I_TOSTOP; }
  319.     if (lflag&ECHOCTL) { flag |= CTLECH; }
  320.     if (lflag&ECHOPRT) { flag |= PRTERA; }
  321.     if (lflag&ECHOKE) { flag |= CRTKIL; }
  322.     if (lflag&ECHO) { flag |= ECHO; }
  323.     if (lflag&T_FLUSHO) { flag |= I_FLUSHO; }
  324.  
  325.     ttyb->sg_flags = flag&0xffff;
  326.     *lmode = flag>>16;
  327.     ttyb->sg_ispeed = cflag&CBAUD;
  328.     ttyb->sg_ospeed = cflag&CBAUD;
  329.     tc->t_intrc = ts->c_cc[VINTR];
  330.     tc->t_quitc = ts->c_cc[VQUIT];
  331.     ttyb->sg_erase = ts->c_cc[VERASE];
  332.     ttyb->sg_kill = ts->c_cc[VKILL];
  333.     tc->t_eofc = ts->c_cc[VEOF];
  334.     if (termiosFlag) {
  335.     tc->t_startc = ts->c_cc[VSTART];
  336.     tc->t_stopc = ts->c_cc[VSTOP];
  337.     ltc->t_suspc = ts->c_cc[VSUSP];
  338.         ltc->t_dsuspc = ts->c_cc[VDSUSP];
  339.     ltc->t_rprntc = ts->c_cc[VREPRINT];
  340.     ltc->t_flushc = ts->c_cc[VDISCARD];
  341.     ltc->t_werasc = ts->c_cc[VWERASE];
  342.     ltc->t_lnextc = ts->c_cc[VLNEXT];
  343.     }
  344. }
  345.  
  346. /*
  347.  *----------------------------------------------------------------------
  348.  *
  349.  * CvtSgttybToTermios --
  350.  *
  351.  *    Convert from termios structure to sgttyb structure.
  352.  *    Note: ttyb and lmode must be initialized on entry.
  353.  *
  354.  * Results:
  355.  *    Changes ts.
  356.  *
  357.  * Side effects:
  358.  *     
  359.  *
  360.  *----------------------------------------------------------------------
  361.  */
  362. static void
  363. CvtSgttybToTermios(ttyb, lmode, tc, ltc, ts)
  364.     struct sgttyb *ttyb;    /* IN */
  365.     unsigned int *lmode;    /* IN */
  366.     struct tchars *tc;        /* IN */
  367.     struct ltchars *ltc;    /* IN */
  368.     struct termios *ts;        /* OUT */
  369. {
  370.     unsigned int flag;
  371.     unsigned int iflag, oflag, cflag, lflag;
  372.  
  373.     flag = ttyb->sg_flags | (*lmode<<16);
  374.     iflag = IMAXBEL|IXON|ISTRIP|IGNPAR|BRKINT|IXANY;
  375.     oflag = ONLRET|OPOST;
  376.     cflag = CREAD|CS8|B9600;
  377.     lflag = ICANON|ISIG|IEXTEN|ECHOK;
  378.     if (flag&CBREAK) { lflag &= ~ICANON; }
  379.     if (flag&TANDEM) { iflag |= IXOFF; }
  380.     if (flag&LCASE) {
  381.     iflag |= IUCLC;
  382.     oflag |= OLCUC;
  383.     lflag |= XCASE;
  384.     }
  385.     if (flag&ECHO) { lflag |= ECHO; }
  386.     if (flag&EVENP) {
  387.     iflag |= INPCK;
  388.     cflag |= PARENB;
  389.     cflag &= ~CS6;
  390.     if (flag&ODDP) {
  391.         iflag &= ~INPCK;
  392.     }
  393.     } else if (flag&ODDP) {
  394.     iflag |= INPCK;
  395.     cflag |= PARODD|PARENB;
  396.     cflag &= ~CS6;
  397.     }
  398.     if ((flag&NLDELAY)==I_NL2) {
  399.     oflag |= T_NL1;
  400.     }
  401.     if (flag&CRMOD) {
  402.     iflag |= ICRNL;
  403.     oflag |= ONLCR;
  404.     oflag &= ~CRDLY;
  405.     } else {
  406.     oflag &= ~CRDLY;
  407.     }
  408.     if (flag&I_TAB1) { oflag |= T_TAB1; }
  409.     if (flag&I_TAB2) { oflag |= T_TAB2; }
  410.     if ((flag&CRDELAY)==I_CR0 || (flag&CRDELAY)==I_CR3) {
  411.     if (!(flag&CRMOD) && (flag&NLDELAY)==I_NL1) {
  412.         oflag |= T_CR1;
  413.     }
  414.     } else if ((flag&CRDELAY)==I_CR1) {
  415.     if (flag&CRMOD) {
  416.         oflag |= T_CR2;
  417.     } else if ((flag&NLDELAY)==I_NL1) {
  418.         oflag |= T_CR1;
  419.     }
  420.     } else if ((flag&CRDELAY)==I_CR2) {
  421.     if (flag&CRMOD) {
  422.         oflag |= T_CR3;
  423.     } else if ((flag&NLDELAY)==I_NL1) {
  424.         oflag |= T_CR1;
  425.     }
  426.     }
  427.     if (flag&VTDELAY) { oflag |= FFDLY; }
  428.     if (flag&BSDELAY) { oflag |= BSDLY; }
  429.     if (flag&PRTERA) { lflag |= ECHOPRT; }
  430.     if (flag&CRTERA) { lflag |= ECHOE; }
  431.     if (flag&I_TOSTOP) { lflag |= TOSTOP; }
  432.     if (flag&I_FLUSHO) { lflag |= FLUSHO; }
  433.     if (flag&NOHANG) { cflag |= CLOCAL; }
  434.     if (flag&CRTKIL) { lflag |= ECHOKE; }
  435.     if (flag&CTLECH) { lflag |= ECHOCTL; }
  436.     if (flag&DECCTQ) { iflag &= ~IXANY; }
  437.     if (flag&I_NOFLSH) { lflag |= T_NOFLSH; }
  438.     if (flag&LITOUT) {
  439.     iflag &= ~(ISTRIP|INPCK);
  440.     oflag &= ~OPOST;
  441.     cflag &= CLOCAL;
  442.     cflag |= CREAD|CS8|B9600;
  443.     }
  444.     if (flag&PASS8) {
  445.     iflag &= ~(ISTRIP|INPCK);
  446.     cflag &= CLOCAL;
  447.     cflag |= CREAD|CS8|B9600;
  448.     }
  449.     if (flag&RAW) {
  450.     iflag &= IXOFF|IXANY;
  451.     oflag &= ~OPOST;
  452.     oflag |= ONLRET;
  453.     lflag &= ~(IEXTEN|ISIG|ICANON|ECHOCTL|XCASE);
  454.     cflag &= ~(PARODD|PARENB);
  455.     cflag |= CREAD|CS8|B9600;
  456.     if ((flag&BSDELAY) && ((flag&CRDELAY==I_CR1))) {
  457.         oflag |= T_CR2;
  458.     }
  459.     }
  460.     cflag |= ttyb->sg_ospeed&CBAUD;
  461.     ts->c_iflag = iflag;
  462.     ts->c_oflag = oflag;
  463.     ts->c_cflag = cflag;
  464.     ts->c_lflag = lflag;
  465.     ts->c_line = 0;
  466.     ts->c_cc[VINTR] = tc->t_intrc;
  467.     ts->c_cc[VQUIT] = tc->t_quitc;
  468.     ts->c_cc[VERASE] = ttyb->sg_erase;
  469.     ts->c_cc[VKILL] = ttyb->sg_kill;
  470.     ts->c_cc[VEOF] = tc->t_eofc;
  471.     ts->c_cc[VEOL] = 0;
  472.     ts->c_cc[VEOL2] = 0;
  473.     ts->c_cc[VSWTCH] = 0;
  474.     ts->c_cc[VSTART] = tc->t_startc;
  475.     ts->c_cc[VSTOP] = tc->t_stopc;
  476.     ts->c_cc[VSUSP] = ltc->t_suspc;
  477.     ts->c_cc[VDSUSP] = ltc->t_dsuspc;
  478.     ts->c_cc[VREPRINT] = ltc->t_rprntc;
  479.     ts->c_cc[VDISCARD] = ltc->t_flushc;
  480.     ts->c_cc[VWERASE] = ltc->t_werasc;
  481.     ts->c_cc[VLNEXT] = ltc->t_lnextc;
  482. }
  483.  
  484. /*
  485.  *----------------------------------------------------------------------
  486.  *
  487.  * GetTermInfo --
  488.  *
  489.  *    Get ttyb, lmode, tc, and ltc.
  490.  *
  491.  * Results:
  492.  *    SUCCESS or FAILURE (returns Sprite error)
  493.  *
  494.  * Side effects:
  495.  *    Changes ttyb, etc.
  496.  *     
  497.  *
  498.  *----------------------------------------------------------------------
  499.  */
  500. static int
  501. GetTermInfo(streamPtr, ioctl, ttyb, lmode, tc, ltc)
  502.     Fs_Stream        *streamPtr;
  503.     Fs_IOCParam        *ioctl;
  504.     struct sgttyb *ttyb;
  505.     unsigned int *lmode;
  506.     struct tchars *tc;
  507.     struct ltchars *ltc;
  508. {
  509.     Fs_IOReply          reply;
  510.     ReturnStatus    status;
  511.  
  512.     ioctl->command = IOC_TTY_GET_PARAMS;
  513.     ioctl->outBufSize = sizeof(struct sgttyb);
  514.     ioctl->outBuffer = (Address) ttyb;
  515.     status = Fs_IOControl(streamPtr, ioctl, &reply);
  516.     if (status == SUCCESS) {
  517.     ioctl->command = IOC_TTY_GET_LM;
  518.     ioctl->outBufSize = sizeof(int);
  519.     ioctl->outBuffer = (Address) lmode;
  520.     status = Fs_IOControl(streamPtr, ioctl, &reply);
  521.     }
  522.     if (status == SUCCESS) {
  523.     ioctl->command = IOC_TTY_GET_TCHARS;
  524.     ioctl->outBufSize = sizeof(struct tchars);
  525.     ioctl->outBuffer = (Address) tc;
  526.     status = Fs_IOControl(streamPtr, ioctl, &reply);
  527.     }
  528.     if (status == SUCCESS) {
  529.     ioctl->command = IOC_TTY_GET_LTCHARS;
  530.     ioctl->outBufSize = sizeof(struct ltchars);
  531.     ioctl->outBuffer = (Address) ltc;
  532.     status = Fs_IOControl(streamPtr, ioctl, &reply);
  533.     }
  534.     if (debugFsStubs) {
  535.     printf("GetTermInfo: werase = %x, int = %x\n", ltc->t_werasc,
  536.         tc->t_intrc);
  537.     }
  538.     if (status != SUCCESS && debugFsStubs) {
  539.     printf("GetTermInfo: status %x\n", status);
  540.     }
  541.     return status;
  542. }
  543.  
  544. /*
  545.  *----------------------------------------------------------------------
  546.  *
  547.  * CheckIfPresent --
  548.  *
  549.  *    Check if a prefix is in the prefix table.  This is so we don't
  550.  *    have to do pointless broadcasts for getwd's.
  551.  *
  552.  * Results:
  553.  *    SUCCESS or FAILURE
  554.  *
  555.  * Side effects:
  556.  *     none.
  557.  *
  558.  *----------------------------------------------------------------------
  559.  */
  560. static ReturnStatus
  561. CheckIfPresent(name)
  562.     char *name;
  563. {
  564.     ReturnStatus    status;
  565.     Fs_HandleHeader    *hdrPtr;
  566.     Fs_FileID        rootID;
  567.     char        *lookupName;
  568.     int            serverID=123;
  569.     int            domainType;
  570.     Fsprefix        *prefixPtr;
  571.     Fs_RedirectInfo    *oldInfoPtr = (Fs_RedirectInfo *)NIL;
  572.     Fs_RedirectInfo    *redirectInfoPtr = (Fs_RedirectInfo *)NIL;
  573.     Fs_OpenArgs        openArgs;
  574.     Fs_GetAttrResults    getAttrResults;
  575.     Proc_ControlBlock    *procPtr = Proc_GetEffectiveProc();
  576.     Fs_FileID        ioFileID;
  577.     Fs_Attributes    attrs;
  578.     int            numRedirects=0;
  579.  
  580.     /*
  581.      * This code if from Fs_GetAttributes);
  582.      */
  583.     openArgs.useFlags = FS_FOLLOW;
  584.     openArgs.permissions = 0;
  585.     openArgs.type = FS_FILE;
  586.     openArgs.clientID = rpc_SpriteID;
  587.     Fs_SetIDs(procPtr, &openArgs.id);
  588.     if (procPtr->genFlags & PROC_FOREIGN) {
  589.     openArgs.migClientID = procPtr->peerHostID;
  590.     } else {
  591.     openArgs.migClientID = rpc_SpriteID;
  592.     }
  593.     getAttrResults.attrPtr = &attrs;
  594.     getAttrResults.fileIDPtr = &ioFileID;
  595.  
  596.     /*
  597.      * This loop is out of Fsprefix_LookupOperation
  598.      */
  599.     while (1) {
  600. #if 1
  601.     /*
  602.      * The next loop is from GetPrefix.
  603.      */
  604.     do {
  605.         status = Fsprefix_Lookup(name, FSPREFIX_IMPORTED, FS_LOCALHOST_ID,
  606.             &hdrPtr, &rootID, &lookupName, &serverID, &domainType,
  607.             &prefixPtr);
  608.         if (status == FS_NO_HANDLE) {
  609.         return FAILURE;
  610.         }
  611.     } while (status == FS_NEW_PREFIX);
  612. #else
  613.     status = GetPrefix(name, FS_FOLLOW, &hdrPtr, &rootID, &lookupName,
  614.         &domainType, &prefixPtr);
  615. #endif
  616.     {
  617.         register Fs_LookupArgs *lookupArgsPtr = (Fs_LookupArgs *)&openArgs;
  618.         lookupArgsPtr->prefixID = hdrPtr->fileID;
  619.         lookupArgsPtr->rootID = rootID;
  620.     }
  621.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_GET_ATTR])
  622.         (hdrPtr, lookupName, &openArgs, &getAttrResults, &redirectInfoPtr);
  623.     if (status==SUCCESS) {
  624.         return SUCCESS;
  625.     } else if (status == FS_LOOKUP_REDIRECT) {
  626.         numRedirects++;
  627.         if (numRedirects > FS_MAX_LINKS) {
  628.         printf("Loop\n");
  629.         break;
  630.         }
  631.         status = FsprefixLookupRedirect(redirectInfoPtr, prefixPtr,
  632.             &name);
  633.         if (oldInfoPtr != (Fs_RedirectInfo *)NIL) {
  634.         free((Address)oldInfoPtr);
  635.         }
  636.         oldInfoPtr = redirectInfoPtr;
  637.         redirectInfoPtr = (Fs_RedirectInfo *)NIL;
  638.     } else {
  639.         break;
  640.     }
  641.     }
  642.  
  643.     return FAILURE;
  644. }
  645.  
  646. /*
  647.  *----------------------------------------------------------------------
  648.  *
  649.  * copyin --
  650.  *
  651.  *    Copy a string from user space to a static buffer.
  652.  *
  653.  * Results:
  654.  *    The string.
  655.  *
  656.  * Side effects:
  657.  *     none.
  658.  *
  659.  *----------------------------------------------------------------------
  660.  */
  661. static char *
  662. copyin(string)
  663.     char *string;
  664. {
  665.     static char buf[FS_MAX_PATH_NAME_LENGTH + 1];
  666.     int x;
  667.  
  668.     assert(debugFsStubs);
  669.     Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, string, buf, &x);
  670.     return buf;
  671. }
  672.  
  673. /*
  674.  *----------------------------------------------------------------------
  675.  *
  676.  * Fs_NewReadStub --
  677.  *
  678.  *    The stub for the "read" Unix system call.
  679.  *
  680.  * Results:
  681.  *    Returns -1 on failure.
  682.  *
  683.  * Side effects:
  684.  *    Side effects associated with the system call.
  685.  *     
  686.  *
  687.  *----------------------------------------------------------------------
  688.  */
  689. int
  690. Fs_NewReadStub(streamID, buffer, numBytes)
  691.     int     streamID;    /* descriptor for stream to read */
  692.     char    *buffer;    /* pointer to buffer area */
  693.     int        numBytes;    /* number of bytes to read */
  694. {
  695.     ReturnStatus    status;
  696.     Proc_ControlBlock    *procPtr;
  697.     Fs_Stream        *streamPtr;
  698.     int                 amountRead;
  699.     int                 totalAmountRead;
  700.  
  701.     if (debugFsStubs) {
  702.     printf("Fs_NewReadStub(%d, %d)\n", streamID, numBytes);
  703.     }
  704.     totalAmountRead = 0;
  705.     procPtr = Proc_GetEffectiveProc();
  706.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  707.     if (status != SUCCESS) {
  708.     Mach_SetErrno(Compat_MapCode(status));
  709.     return -1;
  710.     }
  711.     amountRead = numBytes - totalAmountRead;
  712.     if (debugFsStubs) {
  713.         printf("Fs_Read(%x, %x, %x, %x(%d))\n", streamPtr, buffer,
  714.                 streamPtr->offset, &amountRead, amountRead);
  715.     }
  716.     status = Fs_Read(streamPtr, buffer, streamPtr->offset, &amountRead);
  717.     totalAmountRead += amountRead;
  718.     if (status == GEN_ABORTED_BY_SIGNAL) {
  719.         if (debugFsStubs) {
  720.             printf("Fs_Read aborted by signal\n");
  721.         }
  722.         if (totalAmountRead==0) {
  723.             procPtr->unixProgress = PROC_PROGRESS_RESTART;
  724.             return -1; /* This return value should not get to the user. */
  725.         }
  726.     } else if (status != SUCCESS) {
  727.         Mach_SetErrno(Compat_MapCode(status));
  728.         return -1;
  729.     }
  730.     return totalAmountRead;
  731. }
  732.  
  733. /*
  734.  *----------------------------------------------------------------------
  735.  *
  736.  * Fs_NewWriteStub --
  737.  *
  738.  *    The stub for the "write" Unix system call.
  739.  *
  740.  * Results:
  741.  *    Returns -1 on failure.
  742.  *
  743.  * Side effects:
  744.  *    Side effects associated with the system call.
  745.  *     
  746.  *
  747.  *----------------------------------------------------------------------
  748.  */
  749. int
  750. Fs_NewWriteStub(streamID, buffer, numBytes)
  751.     int     streamID;    /* descriptor for stream to read */
  752.     char    *buffer;    /* pointer to buffer area */
  753.     int        numBytes;    /* number of bytes to read */
  754. {
  755.     ReturnStatus    status;
  756.     Fs_Stream        *streamPtr;
  757.     int                 writeLength;
  758.     int                 totalAmountWritten;
  759.  
  760.     if (debugFsStubs) {
  761.     printf("Fs_NewWriteStub(%d, %d)\n", streamID, numBytes);
  762.     }
  763.     totalAmountWritten = 0;
  764.     status = Fs_GetStreamPtr(Proc_GetEffectiveProc(), streamID, &streamPtr);
  765.     if (status != SUCCESS) {
  766.     Mach_SetErrno(Compat_MapCode(status));
  767.     return -1;
  768.     }
  769.     writeLength = numBytes - totalAmountWritten;
  770.     status = Fs_Write(streamPtr, buffer, streamPtr->offset, &writeLength);
  771.     totalAmountWritten += writeLength;
  772.     if (status == GEN_ABORTED_BY_SIGNAL) {
  773.         if (debugFsStubs) {
  774.             printf("Fs_Write aborted by signal\n");
  775.         }
  776.         if (totalAmountWritten==0) {
  777.             Proc_GetCurrentProc()->unixProgress = PROC_PROGRESS_RESTART;
  778.             return -1; /* This should not get to the user */
  779.         }
  780.     } else if (status != SUCCESS) {
  781.         Mach_SetErrno(Compat_MapCode(status));
  782.         return -1;
  783.     }
  784.     return totalAmountWritten;
  785. }
  786.  
  787. /*
  788.  *----------------------------------------------------------------------
  789.  *
  790.  * Fs_NewOpenStubInt --
  791.  *
  792.  *    The code for the "open" Unix system call.
  793.  *
  794.  * Results:
  795.  *    Returns -1 on failure.
  796.  *
  797.  * Side effects:
  798.  *    Side effects associated with the system call.
  799.  *     
  800.  *
  801.  *----------------------------------------------------------------------
  802.  */
  803. int
  804. Fs_NewOpenStubInt(pathName, unixFlags, permissions)
  805.     int        unixFlags;    /* Unix mode flags. */
  806.     int        permissions;    /* Permission mask to use on creation */
  807.     char    *pathName;    /* The name of the file to open */
  808. {
  809.     ReturnStatus status;    /* result returned by Fs_Open */
  810.     register int useFlags;    /* Sprite version of flags */
  811.     int streamID;
  812.     Fs_Stream         *streamPtr;
  813.  
  814.     /*
  815.      * Convert unixFlags to FS_READ, etc.
  816.      */
  817.     if (debugFsStubs) {
  818.     printf("Fs_NewOpenStubInt(%s, 0x%x, 0x%x)\n",
  819.         copyin(pathName), unixFlags, permissions);
  820.     }
  821.  
  822.     if (unixFlags & FASYNC) {
  823.     printf("open - FASYNC not supported\n");
  824.     Mach_SetErrno(EINVAL);
  825.     return -1;
  826.     }
  827.     if (unixFlags & O_RDWR) {
  828.     useFlags = FS_READ|FS_WRITE;
  829.     } else if (unixFlags & O_WRONLY) {
  830.     useFlags = FS_WRITE;
  831.     } else {
  832.     useFlags = FS_READ;
  833.     }
  834.     if (unixFlags & FNDELAY) {
  835.     useFlags |= FS_NON_BLOCKING;
  836.     }
  837.     if (unixFlags & FAPPEND) {
  838.     useFlags |= FS_APPEND;
  839.     }
  840.     if (unixFlags & FTRUNC) {
  841.     useFlags |= FS_TRUNC;
  842.     }
  843.     if (unixFlags & FEXCL) {
  844.     useFlags |= FS_EXCLUSIVE;
  845.     }
  846.     if (unixFlags & O_MASTER) {
  847.     useFlags |= FS_PDEV_MASTER;
  848.     }
  849.     if (unixFlags & O_PFS_MASTER) {
  850.     useFlags |= FS_PFS_MASTER;
  851.     }
  852.     if (unixFlags & FCREAT) {
  853.     useFlags |= FS_CREATE;
  854.     }
  855.  
  856.     /*
  857.      * Open the file and get a stream descriptor for it.
  858.      */
  859.     useFlags &= ~FS_KERNEL_FLAGS;
  860.     useFlags |= (FS_USER | FS_FOLLOW);
  861.  
  862.     if (debugFsStubs) {
  863.     printf("Fs_NewOpenStubInt: Fs_Open(%s, %x, %x, %x, %x)\n", pathName,
  864.         useFlags, FS_FILE, permissions&0777, &streamPtr);
  865.     }
  866.     status = Fs_Open(pathName, useFlags, FS_FILE,
  867.     permissions & 0777, &streamPtr);
  868.  
  869.     if (status != SUCCESS) {
  870.     if (debugFsStubs) {
  871.         printf("Fs_Open: error %x\n", status);
  872.     }
  873.     Mach_SetErrno(Compat_MapCode(status));
  874.     return -1;
  875.     }
  876.  
  877.     /*
  878.      * Save a pointer to the descriptor in a list kept in the proc table.
  879.      * Its index in the list is the "Stream ID".
  880.      */
  881.     status = Fs_GetStreamID(streamPtr, &streamID);
  882.     if (status != SUCCESS) {
  883.     if (debugFsStubs) {
  884.         printf("open (2) status = %08lx\n", status);
  885.     }
  886.     (void) Fs_Close(streamPtr);
  887.     Mach_SetErrno(Compat_MapCode(status));
  888.     return -1;
  889.     }
  890.     if (debugFsStubs) {
  891.     printf("Fs_NewOpenStubInt: result %d\n", streamID);
  892.     }
  893.     return streamID;
  894. }
  895.  
  896. /*
  897.  *----------------------------------------------------------------------
  898.  *
  899.  * Fs_NewOpenStub --
  900.  *
  901.  *    The stub for the "open" Unix system call.
  902.  *    This routine copies in the pathname and then calls Fs_NewOpenStubInt.
  903.  *
  904.  * Results:
  905.  *    Returns -1 on failure.
  906.  *
  907.  * Side effects:
  908.  *    Side effects associated with the system call.
  909.  *     
  910.  *
  911.  *----------------------------------------------------------------------
  912.  */
  913. int
  914. Fs_NewOpenStub(pathName, unixFlags, permissions)
  915.     char    *pathName;    /* The name of the file to open */
  916.     int        unixFlags;    /* O_RDONLY O_WRONLY O_RDWR O_NDELAY
  917.                  * O_APPEND O_CREAT O_TRUNC O_EXCL */
  918.     int        permissions;    /* Permission mask to use on creation */
  919. {
  920.     int            pathNameLength;
  921.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  922.     Proc_ControlBlock    *procPtr = Proc_GetEffectiveProc();
  923.     /*
  924.      * Copy the name in from user space to the kernel stack.
  925.      */
  926.     procPtr->unixProgress = PROC_PROGRESS_UNIX;
  927.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  928.                &pathNameLength) != SUCCESS) {
  929.     Mach_SetErrno(EACCES);
  930.     if (debugFsStubs) {
  931.         printf("Errno: %x = %d\n", &Proc_GetActualProc()->unixErrno,
  932.             Proc_GetActualProc()->unixErrno);
  933.     }
  934.     return -1;
  935.     }
  936.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  937.     Mach_SetErrno(ENAMETOOLONG);
  938.     return -1;
  939.     }
  940.     return Fs_NewOpenStubInt(newName, unixFlags, permissions);
  941.  
  942. }
  943.  
  944.  
  945. /*
  946.  *----------------------------------------------------------------------
  947.  *
  948.  * Fs_NewCloseStub --
  949.  *
  950.  *    The stub for the "close" Unix system call.
  951.  *
  952.  * Results:
  953.  *    Returns -1 on failure.
  954.  *
  955.  * Side effects:
  956.  *    Side effects associated with the system call.
  957.  *     
  958.  *
  959.  *----------------------------------------------------------------------
  960.  */
  961. int
  962. Fs_NewCloseStub(streamID)
  963.     int streamID;
  964. {
  965.     ReturnStatus status;
  966.  
  967.     if (debugFsStubs) {
  968.     printf("Fs_CloseStub(%d)\n", streamID);
  969.     }
  970.     status = Fs_UserClose(streamID);
  971.  
  972.     if (status != SUCCESS) {
  973.     Mach_SetErrno(Compat_MapCode(status));
  974.     return -1;
  975.     }
  976.     return 0;
  977. }
  978.  
  979. /*
  980.  *----------------------------------------------------------------------
  981.  *
  982.  * Fs_CreatStub --
  983.  *
  984.  *    The stub for the "creat" Unix system call.
  985.  *
  986.  * Results:
  987.  *    Returns -1 on failure.
  988.  *
  989.  * Side effects:
  990.  *    Side effects associated with the system call.
  991.  *     
  992.  *
  993.  *----------------------------------------------------------------------
  994.  */
  995. int
  996. Fs_CreatStub(pathName, permissions)
  997.     char *pathName;        /* The name of the file to create */
  998.     int permissions;        /* Permission mask to use on creation */
  999. {
  1000.  
  1001.     if (debugFsStubs) {
  1002.     printf("Fs_CreatStub(%s, 0x%x)\n", copyin(pathName), permissions);
  1003.     }
  1004.     return (Fs_NewOpenStub(pathName, FS_CREATE|FS_TRUNC|FS_WRITE, permissions));
  1005. }
  1006.  
  1007. /*
  1008.  *----------------------------------------------------------------------
  1009.  *
  1010.  * Fs_ReadvStub --
  1011.  *
  1012.  *    The stub for the "readv" Unix system call.
  1013.  *
  1014.  * Results:
  1015.  *    Returns -1 on failure.
  1016.  *
  1017.  * Side effects:
  1018.  *    Side effects associated with the system call.
  1019.  *     
  1020.  *
  1021.  *----------------------------------------------------------------------
  1022.  */
  1023. #define MAX_IOV 16
  1024. int
  1025. Fs_ReadvStub(streamID, iov, iovcnt)
  1026.     int streamID;        /* descriptor for stream to read. */
  1027.     register struct iovec *iov;    /* pointer to array of iovecs. */
  1028.     int iovcnt;            /* number of  iovecs in iov. */
  1029. {
  1030.     int amountRead;             /* place to hold number of bytes read */
  1031.     int totalRead = 0;          /* place to hold total # of bytes read */
  1032.     int i;
  1033.     int status = SUCCESS;
  1034.     struct iovec iovCopy[MAX_IOV];      /* Kernel copy of iov */
  1035.     Proc_ControlBlock    *procPtr = Proc_GetEffectiveProc();
  1036.  
  1037.     if (debugFsStubs) {
  1038.         printf("Fs_ReadvStub\n");
  1039.     }
  1040.     if (iovcnt<=0 || iovcnt > MAX_IOV) {
  1041.         Mach_SetErrno(EINVAL);
  1042.         return -1;
  1043.     }
  1044.     if (Vm_CopyIn(sizeof(struct iovec)*iovcnt, (Address)iov,
  1045.             (Address)iovCopy) != SUCCESS) {
  1046.         Mach_SetErrno(EFAULT);
  1047.         return -1;
  1048.     }
  1049.     for (i=0; i < iovcnt; i++) {
  1050.         amountRead = Fs_NewReadStub(streamID, iovCopy[i].iov_base,
  1051.                 iovCopy[i].iov_len);
  1052.         if (amountRead == -1) {
  1053.         if (debugFsStubs) {
  1054.         printf("Readv subread failed\n");
  1055.         }
  1056.         status = FAILURE;
  1057.         break;
  1058.         }
  1059.         totalRead += amountRead;
  1060.     if (amountRead < iovCopy[i].iov_len) {
  1061.         if (debugFsStubs) {
  1062.         printf("Readv subread didn't do it all\n");
  1063.         }
  1064.         break;
  1065.     }
  1066.     }
  1067.     /*
  1068.      * If we read anything, it's a success.
  1069.      */
  1070.     if (status == FAILURE && totalRead == 0) {
  1071.     if (debugFsStubs) {
  1072.         printf("Readv failed\n");
  1073.     }
  1074.     return -1;
  1075.     } else {
  1076.     if (debugFsStubs) {
  1077.         printf("Readv: returns %d\n", totalRead);
  1078.     }
  1079.     /*
  1080.      * read may say restart, but if we wrote anything, we don't restart.
  1081.      */
  1082.     procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1083.     return totalRead;
  1084.     }
  1085. }
  1086.  
  1087. /*
  1088.  *----------------------------------------------------------------------
  1089.  *
  1090.  * Fs_WritevStub --
  1091.  *
  1092.  *    The stub for the "writev" Unix system call.
  1093.  *
  1094.  * Results:
  1095.  *    Returns -1 on failure.
  1096.  *
  1097.  * Side effects:
  1098.  *    Side effects associated with the system call.
  1099.  *     
  1100.  *
  1101.  *----------------------------------------------------------------------
  1102.  */
  1103. int
  1104. Fs_WritevStub(streamID, iov, iovcnt)
  1105.     int streamID;        /* descriptor for stream to read. */
  1106.     register struct iovec *iov;    /* pointer to array of iovecs. */
  1107.     int iovcnt;            /* number of  iovecs in iov. */
  1108. {
  1109.     int amountWritten;          /* place to hold number of bytes read */
  1110.     int totalWritten = 0;       /* place to hold total # of bytes written */
  1111.     int i;
  1112.     int status = SUCCESS;
  1113.     struct iovec iovCopy[MAX_IOV];      /* Kernel copy of iov */
  1114.     Proc_ControlBlock    *procPtr = Proc_GetEffectiveProc();
  1115.  
  1116.     if (debugFsStubs) {
  1117.         printf("Fs_WritevStub\n");
  1118.     }
  1119.     if (iovcnt<=0 || iovcnt > MAX_IOV) {
  1120.         Mach_SetErrno(EINVAL);
  1121.         return -1;
  1122.     }
  1123.     if (Vm_CopyIn(sizeof(struct iovec)*iovcnt, (Address)iov,
  1124.             (Address)iovCopy) != SUCCESS) {
  1125.         Mach_SetErrno(EFAULT);
  1126.         return -1;
  1127.     }
  1128.     for (i=0; i < iovcnt; i++) {
  1129.         amountWritten = Fs_NewWriteStub(streamID, iovCopy[i].iov_base,
  1130.                 iovCopy[i].iov_len);
  1131.         if (amountWritten == -1) {
  1132.         if (debugFsStubs) {
  1133.         printf("Writev subwrite failed\n");
  1134.         }
  1135.         status = FAILURE;
  1136.         break;
  1137.         }
  1138.         totalWritten += amountWritten;
  1139.     if (amountWritten < iovCopy[i].iov_len) {
  1140.         if (debugFsStubs) {
  1141.         printf("Writev subwrite didn't do it all\n");
  1142.         }
  1143.         break;
  1144.     }
  1145.     }
  1146.     /*
  1147.      * If we wrote anything, it's a success.
  1148.      */
  1149.     if (status == FAILURE && totalWritten == 0) {
  1150.     if (debugFsStubs) {
  1151.         printf("Writev failed\n");
  1152.     }
  1153.     return -1;
  1154.     } else {
  1155.     /*
  1156.      * write may say restart, but if we wrote anything, we don't restart.
  1157.      */
  1158.     procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1159.     if (debugFsStubs) {
  1160.         printf("Writev: returns %d\n", totalWritten);
  1161.     }
  1162.     return totalWritten;
  1163.     }
  1164. }
  1165.  
  1166. /*
  1167.  *----------------------------------------------------------------------
  1168.  *
  1169.  * Fs_LinkStub --
  1170.  *
  1171.  *    The stub for the "link" Unix system call.
  1172.  *
  1173.  * Results:
  1174.  *    Returns -1 on failure.
  1175.  *
  1176.  * Side effects:
  1177.  *    Side effects associated with the system call.
  1178.  *     
  1179.  *
  1180.  *----------------------------------------------------------------------
  1181.  */
  1182. int
  1183. Fs_LinkStub(fileName, linkName)
  1184.     char *fileName;
  1185.     char *linkName;
  1186. {
  1187.     ReturnStatus status;
  1188.     int            fileNameLength;
  1189.     int            linkNameLength;
  1190.     char        newFileName[FS_MAX_PATH_NAME_LENGTH];
  1191.     char        *newLinkName;
  1192.  
  1193.     if (debugFsStubs) {
  1194.     printf("Fs_LinkStub(%s, %s)\n", copyin(fileName), copyin(linkName));
  1195.     }
  1196.  
  1197.     /*
  1198.      * Copy the filename in from user space onto the kernel stack.
  1199.      */
  1200.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, fileName, newFileName,
  1201.                &fileNameLength) != SUCCESS) {
  1202.     Mach_SetErrno(EACCES);
  1203.     return -1;
  1204.     }
  1205.     if (fileNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1206.     Mach_SetErrno(EINVAL);
  1207.     return -1;
  1208.     }
  1209.  
  1210.     /*
  1211.      * Maybe I could put the link name onto the stack as well but I am 
  1212.      * allocing it here because I'm not sure if the stack is big enough.
  1213.      * Should just make the stack bigger I suppose ...
  1214.      */
  1215.     newLinkName = (char  *) malloc(FS_MAX_PATH_NAME_LENGTH);
  1216.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, linkName, newLinkName,
  1217.                &linkNameLength) == SUCCESS) {
  1218.     if (linkNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1219.         status = FS_INVALID_ARG;
  1220.     } else {
  1221.         status = Fs_HardLink(newFileName, newLinkName);
  1222.     }
  1223.     } else {
  1224.     status = SYS_ARG_NOACCESS;
  1225.     }
  1226.     free((Address) newLinkName);
  1227.     if (status != SUCCESS) {
  1228.     Mach_SetErrno(Compat_MapCode(status));
  1229.     return -1;
  1230.     }
  1231.     return 0;
  1232. }
  1233.  
  1234. /*
  1235.  *----------------------------------------------------------------------
  1236.  *
  1237.  * Fs_UnlinkStub --
  1238.  *
  1239.  *    The stub for the "unlink" Unix system call.
  1240.  *
  1241.  * Results:
  1242.  *    Returns -1 on failure.
  1243.  *
  1244.  * Side effects:
  1245.  *    Side effects associated with the system call.
  1246.  *     
  1247.  *
  1248.  *----------------------------------------------------------------------
  1249.  */
  1250. int
  1251. Fs_UnlinkStub(pathName)
  1252.     char *pathName;
  1253. {
  1254.     ReturnStatus status;
  1255.     int            pathNameLength;
  1256.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  1257.  
  1258.     if (debugFsStubs) {
  1259.     printf("Fs_UnlinkStub(%s)\n", copyin(pathName));
  1260.     }
  1261.     /*
  1262.      * Copy the name in from user space to the kernel stack.
  1263.      */
  1264.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  1265.                &pathNameLength) != SUCCESS) {
  1266.     status = SYS_ARG_NOACCESS;
  1267.     } else if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1268.     status = FS_INVALID_ARG;
  1269.     } else {
  1270.     status = Fs_Remove(newName);
  1271.     }
  1272.     if (status != SUCCESS) {
  1273.     Mach_SetErrno(Compat_MapCode(status));
  1274.     return -1;
  1275.     }
  1276.     return 0;
  1277. }
  1278.  
  1279. /*
  1280.  *----------------------------------------------------------------------
  1281.  *
  1282.  * Fs_ChdirStub --
  1283.  *
  1284.  *    The stub for the "chdir" Unix system call.
  1285.  *
  1286.  * Results:
  1287.  *    Returns -1 on failure.
  1288.  *
  1289.  * Side effects:
  1290.  *    Side effects associated with the system call.
  1291.  *     
  1292.  *
  1293.  *----------------------------------------------------------------------
  1294.  */
  1295. int
  1296. Fs_ChdirStub(pathName)
  1297.     char    *pathName;
  1298. {
  1299.     ReturnStatus status;
  1300.     int        pathNameLength;
  1301.     char    newName[FS_MAX_PATH_NAME_LENGTH];
  1302.  
  1303.     if (debugFsStubs) {
  1304.     printf("Fs_ChdirStub(%s)\n", copyin(pathName));
  1305.     }
  1306.  
  1307.     /*
  1308.      * Copy the name in from user space onto the kernel stack.
  1309.      */
  1310.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  1311.                &pathNameLength) != SUCCESS) {
  1312.     status = SYS_ARG_NOACCESS;
  1313.     } else if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1314.     status = FS_INVALID_ARG;
  1315.     } else {
  1316.     status = Fs_ChangeDir(newName);
  1317.     }
  1318.     if (status != SUCCESS) {
  1319.     Mach_SetErrno(Compat_MapCode(status));
  1320.     return -1;
  1321.     }
  1322.     return 0;
  1323. }
  1324.  
  1325. /*
  1326.  *----------------------------------------------------------------------
  1327.  *
  1328.  * Fs_ChmodStub --
  1329.  *
  1330.  *    The stub for the "chmod" Unix system call.
  1331.  *
  1332.  * Results:
  1333.  *    Returns -1 on failure.
  1334.  *
  1335.  * Side effects:
  1336.  *    Side effects associated with the system call.
  1337.  *     
  1338.  *
  1339.  *----------------------------------------------------------------------
  1340.  */
  1341. int
  1342. Fs_ChmodStub(path, mode)
  1343.     char    *path;
  1344.     int        mode;
  1345. {
  1346.     Fs_Attributes    attr;
  1347.     ReturnStatus    status;
  1348.     int            pathNameLength;
  1349.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  1350.  
  1351.     if (debugFsStubs) {
  1352.     printf("Fs_ChmodStub(%s, %x)\n", copyin(path), mode);
  1353.     }
  1354.     /*
  1355.      * Copy the name in from user space onto the kernel stack.
  1356.      */
  1357.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, path, newName,
  1358.                        &pathNameLength) != SUCCESS) {
  1359.     status = SYS_ARG_NOACCESS;
  1360.     } else if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1361.     status = FS_INVALID_ARG;
  1362.     } else {
  1363.     attr.permissions = mode;
  1364.     status = Fs_SetAttributes(newName, FS_ATTRIB_FILE, &attr, FS_SET_MODE);
  1365.     }
  1366.     if (status != SUCCESS) {
  1367.     Mach_SetErrno(Compat_MapCode(status));
  1368.     return -1;
  1369.     }
  1370.     return 0;
  1371. }
  1372.  
  1373. /*
  1374.  *----------------------------------------------------------------------
  1375.  *
  1376.  * Fs_FchmodStub --
  1377.  *
  1378.  *    The stub for the "fchmod" Unix system call.
  1379.  *
  1380.  * Results:
  1381.  *    Returns -1 on failure.
  1382.  *
  1383.  * Side effects:
  1384.  *    Side effects associated with the system call.
  1385.  *     
  1386.  *
  1387.  *----------------------------------------------------------------------
  1388.  */
  1389. int
  1390. Fs_FchmodStub(fd, mode)
  1391.     int        fd;
  1392.     int        mode;
  1393. {
  1394.     ReturnStatus    status;
  1395.     Fs_Attributes    attr;
  1396.     Fs_Stream        *streamPtr;
  1397.     Fs_UserIDs        ids;
  1398.     Proc_ControlBlock    *procPtr;
  1399.  
  1400.     if (debugFsStubs) {
  1401.     printf("Fs_FchmodStub(%d, %x)\n", fd, mode);
  1402.     }
  1403.  
  1404.     /*
  1405.      * Map from stream ID to file pointer and get the attributes.
  1406.      */
  1407.     procPtr = Proc_GetEffectiveProc();
  1408.     status = Fs_GetStreamPtr(procPtr, fd, &streamPtr);
  1409.     if (status == SUCCESS) {
  1410.     Fs_SetIDs(procPtr, &ids);
  1411.     attr.permissions = mode;
  1412.     status = Fs_SetAttrStream(streamPtr, &attr, &ids, FS_SET_MODE);
  1413.     }
  1414.     if (status != SUCCESS) {
  1415.     Mach_SetErrno(Compat_MapCode(status));
  1416.     return -1;
  1417.     }
  1418.     return 0;
  1419. }
  1420.  
  1421. /*
  1422.  *----------------------------------------------------------------------
  1423.  *
  1424.  * Fs_ChownStub --
  1425.  *
  1426.  *    The stub for the "chown" Unix system call.
  1427.  *
  1428.  * Results:
  1429.  *    Returns -1 on failure.
  1430.  *
  1431.  * Side effects:
  1432.  *    Side effects associated with the system call.
  1433.  *     
  1434.  *
  1435.  *----------------------------------------------------------------------
  1436.  */
  1437. int
  1438. Fs_ChownStub(path, owner, group)
  1439.     char *path;
  1440.     int owner;
  1441.     int group;
  1442. {
  1443.     ReturnStatus    status;    /* result returned by Sprite system calls */
  1444.     Fs_Attributes   attr;     /* struct containing all file attributes.
  1445.                  * only ownership is looked at. */
  1446.     int                pathNameLength;
  1447.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  1448.  
  1449.     if (debugFsStubs) {
  1450.     printf("Fs_ChownStub(%s, %d, %d)\n", copyin(path), owner, group);
  1451.     }
  1452.  
  1453.     /*
  1454.      * Copy the name in from user space onto the kernel stack.
  1455.      */
  1456.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, path, newName,
  1457.                &pathNameLength) != SUCCESS) {
  1458.     status = SYS_ARG_NOACCESS;
  1459.     } else if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1460.     status = FS_INVALID_ARG;
  1461.     } else {
  1462.     attr.uid = owner;
  1463.     attr.gid = group;
  1464.     status = Fs_SetAttributes(newName, FS_ATTRIB_LINK, &attr, FS_SET_OWNER);
  1465.     }
  1466.     if (status != SUCCESS) {
  1467.     Mach_SetErrno(Compat_MapCode(status));
  1468.     return -1;
  1469.     }
  1470.     return 0;
  1471. }
  1472.  
  1473. /*
  1474.  *----------------------------------------------------------------------
  1475.  *
  1476.  * Fs_FchownStub --
  1477.  *
  1478.  *    The stub for the "fchown" Unix system call.
  1479.  *
  1480.  * Results:
  1481.  *    Returns -1 on failure.
  1482.  *
  1483.  * Side effects:
  1484.  *    Side effects associated with the system call.
  1485.  *     
  1486.  *
  1487.  *----------------------------------------------------------------------
  1488.  */
  1489. int
  1490. Fs_FchownStub(fd, owner, group)
  1491.     int fd;
  1492.     int owner;
  1493.     int group;
  1494. {
  1495.     ReturnStatus status;    /* result returned by Sprite system calls */
  1496.     Fs_Attributes attr;     /* struct containing all file attributes.
  1497.                  * only ownership is looked at. */
  1498.     Fs_Stream            *streamPtr;
  1499.     Fs_UserIDs            ids;
  1500.     Proc_ControlBlock        *procPtr;
  1501.  
  1502.     if (debugFsStubs) {
  1503.     printf("Fs_FchownStub(%d, %d, %d)\n", fd,  owner, group);
  1504.     }
  1505.     /*
  1506.      * Map from stream ID to file pointer and get the attributes.
  1507.      */
  1508.     procPtr = Proc_GetEffectiveProc();
  1509.     status = Fs_GetStreamPtr(procPtr, fd, &streamPtr);
  1510.     if (status == SUCCESS) {
  1511.     Fs_SetIDs(procPtr, &ids);
  1512.     attr.uid = owner;
  1513.     attr.gid = group;
  1514.     status = Fs_SetAttrStream(streamPtr, &attr, &ids, FS_SET_OWNER);
  1515.     }
  1516.     if (status != SUCCESS) {
  1517.     Mach_SetErrno(Compat_MapCode(status));
  1518.     return -1;
  1519.     }
  1520.     return 0;
  1521. }
  1522.  
  1523. /*
  1524.  *----------------------------------------------------------------------
  1525.  *
  1526.  * Fs_IoctlInt --
  1527.  *
  1528.  *    Do an ioctl.  This routine initalizes the ioctl structure and
  1529.  *    performs the ioctl.
  1530.  *
  1531.  * Results:
  1532.  *    Returns -1 on failure.  Sets errno on failure.  Also returns error
  1533.  *    through err.
  1534.  *
  1535.  * Side effects:
  1536.  *    Side effects associated with the ioctl.
  1537.  *     
  1538.  *
  1539.  *----------------------------------------------------------------------
  1540.  */
  1541. int
  1542. Fs_IoctlInt(streamID, command, inBufSize, inBuf, outBufSize, outBuf,
  1543.     reply, err)
  1544.     int            streamID;
  1545.     int            command;
  1546.     Address        inBuf, outBuf;
  1547.     int            inBufSize, outBufSize;
  1548.     Fs_IOReply          *reply;
  1549.     int            *err;
  1550. {
  1551.     Fs_IOCParam         ioctl;
  1552.     Proc_ControlBlock *procPtr;
  1553.     ReturnStatus status;
  1554.     Fs_Stream *streamPtr;
  1555.  
  1556.     if (debugFsStubs) {
  1557.     printf("Fs_IoctlInt(%d, %d, %x, %x, %x, %x, %x, %x)\n", streamID,
  1558.         command, inBufSize ,inBuf, outBufSize, outBuf, reply, err);
  1559.     }
  1560.     procPtr = Proc_GetEffectiveProc();
  1561.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  1562.     if (status == SUCCESS) {
  1563.     ioctl.command = command;
  1564.     ioctl.inBuffer = inBuf;
  1565.     ioctl.inBufSize = inBufSize;
  1566.     ioctl.outBuffer = outBuf;
  1567.     ioctl.outBufSize = outBufSize;
  1568.     ioctl.format = mach_Format;
  1569.     ioctl.procID = procPtr->processID;
  1570.     ioctl.familyID = procPtr->familyID;
  1571.     ioctl.uid = procPtr->effectiveUserID;
  1572.     ioctl.flags = 0;
  1573.     status = Fs_IOControl(streamPtr, &ioctl, reply);
  1574.     }
  1575.     if (status != SUCCESS) {
  1576.     if (debugFsStubs) {
  1577.         printf("Ioctl %x failed\n", command);
  1578.     }
  1579.     *err= Compat_MapCode(status);
  1580.     Mach_SetErrno(*err);
  1581.     return -1;
  1582.     }
  1583.     return 0;
  1584. }
  1585.  
  1586. /*
  1587.  *----------------------------------------------------------------------
  1588.  *
  1589.  * Fs_LseekStub --
  1590.  *
  1591.  *    The stub for the "lseek" Unix system call.
  1592.  *
  1593.  * Results:
  1594.  *    Returns -1 on failure.
  1595.  *
  1596.  * Side effects:
  1597.  *    Side effects associated with the system call.
  1598.  *     
  1599.  *
  1600.  *----------------------------------------------------------------------
  1601.  */
  1602. int
  1603. Fs_LseekStub(streamID, offset, whence)
  1604.     int streamID;            /* array of stream identifiers */
  1605.     long offset;
  1606.     int whence;
  1607. {
  1608.     int    status;
  1609.     Ioc_RepositionArgs inArgs;
  1610.  
  1611.     long                retVal;
  1612.     int            err;
  1613.     Fs_IOReply          reply;
  1614.  
  1615.     if (debugFsStubs) {
  1616.     printf("Fs_LseekStub(%d, 0x%x, %d)\n", streamID, offset, whence);
  1617.     }
  1618.     switch(whence) {
  1619.  
  1620.     case L_SET:
  1621.         inArgs.base = IOC_BASE_ZERO;
  1622.         break;
  1623.  
  1624.     case L_INCR:
  1625.         inArgs.base = IOC_BASE_CURRENT;
  1626.         break;
  1627.  
  1628.     case L_XTND:
  1629.         inArgs.base = IOC_BASE_EOF;
  1630.         break;
  1631.  
  1632.     default:
  1633.         Mach_SetErrno(EINVAL);
  1634.         return -1;
  1635.     }
  1636.     inArgs.offset = offset;
  1637.     if (debugFsStubs) {
  1638.     printf("ioctl: %d, %d\n", inArgs.offset, inArgs.base);
  1639.     }
  1640.     status = Fs_IoctlInt(streamID, IOC_REPOSITION, sizeof(Ioc_RepositionArgs),
  1641.         (Address)&inArgs, sizeof(retVal), (Address)&retVal, &reply, &err);
  1642.     if (status < 0) {
  1643.     return -1;
  1644.     } else {
  1645.     return retVal;
  1646.     }
  1647. }
  1648.  
  1649. /*
  1650.  *----------------------------------------------------------------------
  1651.  *
  1652.  * Fs_AccessStub --
  1653.  *
  1654.  *    The stub for the "access" Unix system call.
  1655.  *
  1656.  * Results:
  1657.  *    Returns -1 on failure.
  1658.  *
  1659.  * Side effects:
  1660.  *    Side effects associated with the system call.
  1661.  *     
  1662.  *
  1663.  *----------------------------------------------------------------------
  1664.  */
  1665. int
  1666. Fs_AccessStub(pathName, mode)
  1667.     char *pathName;        /* The name of the file to open */
  1668.     int     mode;            /* access mode to test for */
  1669. {
  1670.     ReturnStatus status;
  1671.     int spriteMode;
  1672.  
  1673.     if (debugFsStubs) {
  1674.     printf("Fs_AccessStub(%s, %d)\n", copyin(pathName), mode);
  1675.     }
  1676.     if (mode == F_OK) {
  1677.     spriteMode = FS_EXISTS;
  1678.     } else {
  1679.     spriteMode = ((mode&R_OK)?FS_READ:0) | ((mode&W_OK)?FS_WRITE:0) |
  1680.         ((mode&X_OK)?FS_EXECUTE:0);
  1681.     }
  1682.     status = Fs_CheckAccess(pathName, spriteMode, TRUE);
  1683.     if (status != SUCCESS) {
  1684.     Mach_SetErrno(Compat_MapCode(status));
  1685.     return -1;
  1686.     }
  1687.     return 0;
  1688. }
  1689.  
  1690.  
  1691. /*
  1692.  *----------------------------------------------------------------------
  1693.  *
  1694.  * Fs_FsyncStub --
  1695.  *
  1696.  *    The stub for the "fsync" Unix system call.
  1697.  *
  1698.  * Results:
  1699.  *    Returns -1 on failure.
  1700.  *
  1701.  * Side effects:
  1702.  *    Side effects associated with the system call.
  1703.  *     
  1704.  *
  1705.  *----------------------------------------------------------------------
  1706.  */
  1707. int
  1708. Fs_FsyncStub(fd)
  1709.     int fd;
  1710. {
  1711.     ReturnStatus status;
  1712.  
  1713.     if (debugFsStubs) {
  1714.     printf("Fs_FsyncStub\n");
  1715.     }
  1716.     status = Fs_FileWriteBackStub(fd, -1, -1, 1);
  1717.     if (status != SUCCESS) {
  1718.     Mach_SetErrno(Compat_MapCode(status));
  1719.     return -1;
  1720.     }
  1721.     return 0;
  1722. }
  1723.  
  1724.  
  1725.  
  1726.  
  1727. /*
  1728.  *----------------------------------------------------------------------
  1729.  *
  1730.  * Fs_StatStub --
  1731.  *
  1732.  *    The stub for the "stat" Unix system call.
  1733.  *
  1734.  * Results:
  1735.  *    Returns -1 on failure.
  1736.  *
  1737.  * Side effects:
  1738.  *    Side effects associated with the system call.
  1739.  *     
  1740.  *
  1741.  *----------------------------------------------------------------------
  1742.  */
  1743. int
  1744. Fs_StatStub(pathName, attrsBufPtr)
  1745.     char *pathName;        /* The name of the file to stat */
  1746.     struct stat *attrsBufPtr;    /* ptr to buffer to hold attributes in 
  1747.                    Unix format */
  1748. {
  1749.     ReturnStatus     status;    /* status returned by Fs_GetAttributes */
  1750.     Fs_Attributes    spriteAttrs;    /* buffer for attributes using
  1751.                        Sprite format. */
  1752.     struct stat        tmpAttrsBuf;
  1753.     int            pathNameLength;
  1754.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  1755.  
  1756.     if (debugFsStubs) {
  1757.     printf("Fs_StatStub(%s)\n", copyin(pathName));
  1758.     }
  1759.     /*
  1760.      * Copy the name in from user space onto the kernel stack.
  1761.      */
  1762.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  1763.                &pathNameLength) != SUCCESS) {
  1764.     status = SYS_ARG_NOACCESS;
  1765.     if (debugFsStubs) {
  1766.         printf("Fs_StatStub: arg no access\n");
  1767.     }
  1768.     } else if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1769.     status = FS_INVALID_ARG;
  1770.     if (debugFsStubs) {
  1771.         printf("Fs_StatStub: len\n");
  1772.     }
  1773.     } else {
  1774.     if (CheckIfPresent(newName) != SUCCESS) {
  1775.         Mach_SetErrno(ENOENT);
  1776.         return -1;
  1777.     }
  1778.     status = Fs_GetAttributes(newName, FS_ATTRIB_FILE, &spriteAttrs);
  1779.     if (status == SUCCESS) {
  1780.         CvtSpriteToUnixAtts(&spriteAttrs, &tmpAttrsBuf);
  1781.         /*
  1782.          * The Unix stat structure is 8 bytes shorter than in stat.h
  1783.          */
  1784.         status = Vm_CopyOut(sizeof(struct stat)-8, (Address) &tmpAttrsBuf,
  1785.             (Address) attrsBufPtr);
  1786.     }
  1787.     }
  1788.     if (status != SUCCESS) {
  1789.     if (debugFsStubs) {
  1790.         printf("Fs_StatStub: failure\n");
  1791.     }
  1792.     Mach_SetErrno(Compat_MapCode(status));
  1793.     return -1;
  1794.     }
  1795.     return 0;
  1796. }
  1797.  
  1798.  
  1799. /*
  1800.  *----------------------------------------------------------------------
  1801.  *
  1802.  * Fs_LstatStub --
  1803.  *
  1804.  *    The stub for the "lstat" Unix system call.
  1805.  *
  1806.  * Results:
  1807.  *    Returns -1 on failure.
  1808.  *
  1809.  * Side effects:
  1810.  *    Side effects associated with the system call.
  1811.  *     
  1812.  *
  1813.  *----------------------------------------------------------------------
  1814.  */
  1815. int
  1816. Fs_LstatStub(pathName, attrsBufPtr)
  1817.     char *pathName;        /* The name of the file to stat */
  1818.     struct stat *attrsBufPtr;    /* ptr to buffer to hold attributes in 
  1819.                    Unix format */
  1820. {
  1821.     ReturnStatus     status;    /* status returned by Fs_GetAttributes */
  1822.     Fs_Attributes    spriteAttrs;    /* buffer for attributes using
  1823.                        Sprite format. */
  1824.     struct stat        tmpAttrsBuf;
  1825.     int            pathNameLength;
  1826.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  1827.  
  1828.     if (debugFsStubs) {
  1829.     printf("Fs_LstatStub(%s)\n", copyin(pathName));
  1830.     }
  1831.     /*
  1832.      * Copy the name in from user space onto the kernel stack.
  1833.      */
  1834.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  1835.                &pathNameLength) != SUCCESS) {
  1836.     status = SYS_ARG_NOACCESS;
  1837.     } else if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1838.     status = FS_INVALID_ARG;
  1839.     } else {
  1840.     status = Fs_GetAttributes(newName, FS_ATTRIB_LINK, &spriteAttrs);
  1841.     if (CheckIfPresent(newName) == SUCCESS) {
  1842.         /*
  1843.          * See if we just got a remote link.  If so turn around and do
  1844.          * a normal stat because in compatibility mode we want to
  1845.          * follow remote links.
  1846.          */
  1847.         if (spriteAttrs.type == FS_REMOTE_LINK) {
  1848.            status = Fs_GetAttributes(newName,FS_ATTRIB_FILE,&spriteAttrs);
  1849.         }
  1850.     } else {
  1851.         if (debugFsStubs) {
  1852.         printf("Skipping stat of remote link\n");
  1853.         }
  1854.     }
  1855.     if (status == SUCCESS) {
  1856.         CvtSpriteToUnixAtts(&spriteAttrs, &tmpAttrsBuf);
  1857.         /*
  1858.          * The Unix stat structure is 8 bytes shorter than in stat.h
  1859.          */
  1860.         status = Vm_CopyOut(sizeof(struct stat)-8, (Address) &tmpAttrsBuf,
  1861.             (Address) attrsBufPtr);
  1862.     }
  1863.     }
  1864.     if (status != SUCCESS) {
  1865.     Mach_SetErrno(Compat_MapCode(status));
  1866.     return -1;
  1867.     }
  1868.     return 0;
  1869. }
  1870.  
  1871. /*
  1872.  *----------------------------------------------------------------------
  1873.  *
  1874.  * Fs_FstatStub --
  1875.  *
  1876.  *    The stub for the "fstat" Unix system call.
  1877.  *
  1878.  * Results:
  1879.  *    Returns -1 on failure.
  1880.  *
  1881.  * Side effects:
  1882.  *    Side effects associated with the system call.
  1883.  *     
  1884.  *
  1885.  *----------------------------------------------------------------------
  1886.  */
  1887. int
  1888. Fs_FstatStub(streamID, attrsBufPtr)
  1889.     int    streamID;        /* The name of the file to stat */
  1890.     struct stat *attrsBufPtr;    /* ptr to user buffer to hold attributes in 
  1891.                    Unix format */
  1892. {
  1893.     ReturnStatus     status;    /* status returned by Fs_GetAttributes */
  1894.     Fs_Attributes    spriteAttrs;    /* buffer for attributes using
  1895.                        Sprite format. */
  1896.     struct stat        tmpAttrsBuf;
  1897.     Fs_Stream        *streamPtr;
  1898.  
  1899.     if (debugFsStubs) {
  1900.     printf("Fs_FstatStub(%d)\n", streamID);
  1901.     }
  1902.     status = Fs_GetStreamPtr(Proc_GetEffectiveProc(), streamID, &streamPtr);
  1903.     if (status == SUCCESS) {
  1904.     status = Fs_GetAttrStream(streamPtr, &spriteAttrs);
  1905.     if (status == SUCCESS) {
  1906.         CvtSpriteToUnixAtts(&spriteAttrs, &tmpAttrsBuf);
  1907.         /*
  1908.          * The Unix stat structure is 8 bytes shorter than in stat.h
  1909.          */
  1910.         status = Vm_CopyOut(sizeof(struct stat)-8, (Address) &tmpAttrsBuf,
  1911.             (Address) attrsBufPtr);
  1912.     }
  1913.     }
  1914.     if (status != SUCCESS) {
  1915.     if (debugFsStubs) {
  1916.         printf("Fs_Fstat failed\n");
  1917.     }
  1918.     Mach_SetErrno(Compat_MapCode(status));
  1919.     return -1;
  1920.     }
  1921.     return 0;
  1922. }
  1923.  
  1924. /*
  1925.  *----------------------------------------------------------------------
  1926.  *
  1927.  * Fs_DupStub --
  1928.  *
  1929.  *    The stub for the "dup" Unix system call.
  1930.  *
  1931.  * Results:
  1932.  *    Returns -1 on failure.
  1933.  *
  1934.  * Side effects:
  1935.  *    Side effects associated with the system call.
  1936.  *     
  1937.  *
  1938.  *----------------------------------------------------------------------
  1939.  */
  1940. int
  1941. Fs_DupStub(oldStreamID)
  1942.     int oldStreamID;
  1943. {
  1944.     ReturnStatus    status;
  1945.     int         newStreamID;
  1946.  
  1947.     if (debugFsStubs) {
  1948.     printf("Fs_DupStub(%d)\n", oldStreamID);
  1949.     }
  1950.     newStreamID = FS_ANYID;
  1951.     status = Fs_GetNewID(oldStreamID, &newStreamID);
  1952.     if (status != SUCCESS) {
  1953.     Mach_SetErrno(Compat_MapCode(status));
  1954.     return -1;
  1955.     }
  1956.     return newStreamID;
  1957. }
  1958.  
  1959. /*
  1960.  *----------------------------------------------------------------------
  1961.  *
  1962.  * Fs_Dup2Stub --
  1963.  *
  1964.  *    The stub for the "dup2" Unix system call.
  1965.  *
  1966.  * Results:
  1967.  *    Returns -1 on failure.
  1968.  *
  1969.  * Side effects:
  1970.  *    Side effects associated with the system call.
  1971.  *     
  1972.  *
  1973.  *----------------------------------------------------------------------
  1974.  */
  1975. int
  1976. Fs_Dup2Stub(oldStreamID, newStreamID)
  1977.     int oldStreamID;        /* original stream identifier */
  1978.     int newStreamID;        /* new stream identifier */
  1979. {
  1980.     ReturnStatus    status;
  1981.  
  1982.     if (debugFsStubs) {
  1983.     printf("Fs_Dup2Stub(%d, %d)\n", oldStreamID, newStreamID);
  1984.     }
  1985.     status = Fs_GetNewID(oldStreamID, &newStreamID);
  1986.     if (status != SUCCESS) {
  1987.     Mach_SetErrno(Compat_MapCode(status));
  1988.     return -1;
  1989.     }
  1990.     return newStreamID;
  1991. }
  1992.  
  1993. /*
  1994.  *----------------------------------------------------------------------
  1995.  *
  1996.  * Fs_PipeStub --
  1997.  *
  1998.  *    The stub for the "pipe" Unix system call.
  1999.  *    This code is ripped off from Fs_CreatePipeStub.
  2000.  *
  2001.  * Results:
  2002.  *    Returns -1 on failure.
  2003.  *
  2004.  * Side effects:
  2005.  *    Creates a pipe.
  2006.  *     
  2007.  *
  2008.  *----------------------------------------------------------------------
  2009.  */
  2010. int
  2011. Fs_PipeStub()
  2012. {
  2013.     ReturnStatus    status;
  2014.     Fs_Stream        *inStreamPtr, *outStreamPtr;
  2015.     int            inStreamID, outStreamID;
  2016.  
  2017.     if (debugFsStubs) {
  2018.     printf("Fs_PipeStub\n");
  2019.     }
  2020.     status = Fsio_CreatePipe(&inStreamPtr, &outStreamPtr);
  2021.     if (status != SUCCESS) {
  2022.     Mach_SetErrno(Compat_MapCode(status));
  2023.     return -1;
  2024.     }
  2025.     inStreamPtr->flags |= FS_USER;
  2026.     outStreamPtr->flags |= FS_USER;
  2027.  
  2028.     /*
  2029.      * Get stream ids for the two streams.
  2030.      */
  2031.     status = Fs_GetStreamID(inStreamPtr, &inStreamID);
  2032.     if (status != SUCCESS) {
  2033.         (void) Fs_Close(inStreamPtr);
  2034.         (void) Fs_Close(outStreamPtr);
  2035.     Mach_SetErrno(Compat_MapCode(status));
  2036.     return -1;
  2037.     }
  2038.     status = Fs_GetStreamID(outStreamPtr, &outStreamID);
  2039.     if (status != SUCCESS) {
  2040.         Fs_ClearStreamID(inStreamID, (Proc_ControlBlock *)NIL);
  2041.         (void) Fs_Close(inStreamPtr);
  2042.         (void) Fs_Close(outStreamPtr);
  2043.     Mach_SetErrno(Compat_MapCode(status));
  2044.     return -1;
  2045.     }
  2046.     if (debugFsStubs) {
  2047.     printf("Fs_PipeStub: return %d, %d\n", inStreamID, outStreamID);
  2048.     }
  2049.     Mach_Return2(outStreamID);
  2050.     return inStreamID;
  2051. }
  2052.  
  2053. /*
  2054.  *----------------------------------------------------------------------
  2055.  *
  2056.  * Fs_SymlinkStub --
  2057.  *
  2058.  *    The stub for the "symlink" Unix system call.
  2059.  *
  2060.  * Results:
  2061.  *    Returns -1 on failure.
  2062.  *
  2063.  * Side effects:
  2064.  *    Side effects associated with the system call.
  2065.  *     
  2066.  *
  2067.  *----------------------------------------------------------------------
  2068.  */
  2069. int
  2070. Fs_SymlinkStub(target, link) 
  2071.     char *target;
  2072.     char *link;
  2073. {
  2074.     ReturnStatus    status;
  2075.  
  2076.     if (debugFsStubs) {
  2077.     printf("Fs_SymlinkStub\n");
  2078.     }
  2079.     status = Fs_SymLinkStub(target, link, FALSE);
  2080.     if (status != SUCCESS) {
  2081.     Mach_SetErrno(Compat_MapCode(status));
  2082.     return -1;
  2083.     }
  2084.     return 0;
  2085. }
  2086.  
  2087. /*
  2088.  *----------------------------------------------------------------------
  2089.  *
  2090.  * Fs_ReadlinkStub --
  2091.  *
  2092.  *    The stub for the "readlink" Unix system call.
  2093.  *
  2094.  * Results:
  2095.  *    Returns -1 on failure.
  2096.  *
  2097.  * Side effects:
  2098.  *    Side effects associated with the system call.
  2099.  *     
  2100.  *
  2101.  *----------------------------------------------------------------------
  2102.  */
  2103. int
  2104. Fs_ReadlinkStub(linkName, buffer, bufSize)
  2105.     char *linkName;        /* name of link file to read */
  2106.     char *buffer;        /* pointer to buffer area */
  2107.     int   bufSize;        /* number of bytes to read */
  2108. {
  2109.     ReturnStatus    status;
  2110.     Fs_Stream        *streamPtr;
  2111.     int            linkNameLength;
  2112.     char        newLinkName[FS_MAX_PATH_NAME_LENGTH];
  2113.     int             linkSize;
  2114.  
  2115.     if (debugFsStubs) {
  2116.     printf("Fs_ReadlinkStub\n");
  2117.     }
  2118.     /*
  2119.      * Copy the name in from user space onto the kernel stack.
  2120.      */
  2121.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, linkName, newLinkName,
  2122.                &linkNameLength) != SUCCESS) {
  2123.     status = SYS_ARG_NOACCESS;
  2124.     } else if (linkNameLength == FS_MAX_PATH_NAME_LENGTH) {
  2125.     status = FS_INVALID_ARG;
  2126.     } else {
  2127.     status = Fs_Open(newLinkName, FS_READ | FS_USER,
  2128.                      FS_SYMBOLIC_LINK|FS_REMOTE_LINK, 0, &streamPtr);
  2129.     if (status == SUCCESS) {
  2130.         status = Fs_Read(streamPtr, buffer, 0, &bufSize);
  2131.         if (status == SUCCESS) {
  2132.         /*
  2133.          * Sprite's link count includes the terminating null character
  2134.          * in the character count return while Unix doesn't.  Make our
  2135.          * count backward-compatible with Unix.
  2136.          */
  2137.         if (buffer[bufSize-1] == '\0') {
  2138.             bufSize--;
  2139.         }
  2140.         status = Proc_ByteCopy(TRUE, sizeof(int), (Address)&bufSize, 
  2141.                                (Address) &linkSize);
  2142.         }
  2143.         (void)Fs_Close(streamPtr);
  2144.     }
  2145.     }
  2146.     if (status != SUCCESS) {
  2147.     Mach_SetErrno(Compat_MapCode(status));
  2148.     return -1;
  2149.     }
  2150.     return bufSize;
  2151. }
  2152.  
  2153. /*
  2154.  *----------------------------------------------------------------------
  2155.  *
  2156.  * Fs_IoctlStub --
  2157.  *
  2158.  *    The stub for the "ioctl" Unix system call.
  2159.  *
  2160.  * Results:
  2161.  *    Returns -1 on failure.
  2162.  *
  2163.  * Side effects:
  2164.  *    Side effects associated with the system call.
  2165.  *     
  2166.  *
  2167.  *----------------------------------------------------------------------
  2168.  */
  2169. int
  2170. Fs_IoctlStub(streamID, request, buf)
  2171.     int  streamID;
  2172.     int  request;
  2173.     char *buf;
  2174. {
  2175.     Proc_ControlBlock   *procPtr;
  2176.     Fs_Stream             *streamPtr;
  2177.     ReturnStatus        status = SUCCESS;
  2178.     Fs_IOCParam         ioctl;
  2179.     Fs_IOReply          reply;
  2180.     int                 flags;
  2181.  
  2182.     if (debugFsStubs) {
  2183.     printf("Fs_IoctlStub(%d, 0x%x)\n", streamID, request);
  2184.     }
  2185.  
  2186.     /*
  2187.      * Get a stream pointer.
  2188.      */
  2189.     procPtr = Proc_GetEffectiveProc();
  2190.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  2191.     if (status != SUCCESS) {
  2192.     Mach_SetErrno(Compat_MapCode(status));
  2193.     return -1;
  2194.     }
  2195.     if (!Fsutil_HandleValid(streamPtr->ioHandlePtr)) {
  2196.     Mach_SetErrno(EBADF);
  2197.     return -1;
  2198.     }
  2199.     ioctl.format = mach_Format;
  2200.     ioctl.procID = procPtr->processID;
  2201.     ioctl.familyID = procPtr->familyID;
  2202.     ioctl.uid = procPtr->effectiveUserID;
  2203.     ioctl.inBuffer = NULL;
  2204.     ioctl.inBufSize = 0;
  2205.     ioctl.outBuffer = NULL;
  2206.     ioctl.outBufSize = 0;
  2207.     ioctl.flags = 0;
  2208.     switch (request) {
  2209.  
  2210.     case FIOCLEX:
  2211.     if (debugFsStubs) {
  2212.                 printf("ioctl: FIOCLEX\n");
  2213.                 }
  2214.     ioctl.command = IOC_SET_BITS;
  2215.     ioctl.inBufSize = sizeof(int);
  2216.     ioctl.inBuffer = (Address) &flags;
  2217.     flags = IOC_CLOSE_ON_EXEC;
  2218.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2219.     procPtr->fsPtr->streamFlags[streamID] |= FS_CLOSE_ON_EXEC;
  2220.     break;
  2221.  
  2222.     case FIONCLEX:
  2223.     if (debugFsStubs) {
  2224.                 printf("ioctl: FIONCLEX\n");
  2225.                 }
  2226.     ioctl.command = IOC_CLEAR_BITS;
  2227.     ioctl.inBufSize = sizeof(int);
  2228.     ioctl.inBuffer = (Address) &flags;
  2229.     flags = IOC_CLOSE_ON_EXEC;
  2230.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2231.     procPtr->fsPtr->streamFlags[streamID] &= ~FS_CLOSE_ON_EXEC;
  2232.     break;
  2233.  
  2234.  
  2235.     case FIONREAD: {
  2236.     int result;
  2237.     if (debugFsStubs) {
  2238.                 printf("ioctl: FIONREAD\n");
  2239.                 }
  2240.     ioctl.command = IOC_NUM_READABLE;
  2241.     ioctl.outBuffer = (Address) &result;
  2242.     ioctl.outBufSize = sizeof(int);
  2243.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2244.     if (status == SUCCESS) {
  2245.         status = Vm_CopyOut(sizeof(int), (Address) &result, buf);
  2246.     }
  2247.     break;
  2248.     }
  2249.  
  2250.  
  2251.     case FIONBIO:
  2252.     if (debugFsStubs) {
  2253.                 printf("ioctl: FIONBIO\n");
  2254.                 }
  2255.     if (Vm_CopyIn(4, buf, (Address) &flags) != SUCCESS) {
  2256.         Mach_SetErrno(EINVAL);
  2257.         return -1;
  2258.     }
  2259.     if (flags) {
  2260.         ioctl.command = IOC_SET_BITS;
  2261.     } else {
  2262.         ioctl.command = IOC_CLEAR_BITS;
  2263.     }
  2264.     ioctl.inBufSize = sizeof(int);
  2265.     ioctl.inBuffer = (Address) &flags;
  2266.     flags = IOC_NON_BLOCKING;
  2267.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2268.     break;
  2269.  
  2270.     case FIOASYNC:
  2271.     if (debugFsStubs) {
  2272.                 printf("ioctl: FIOASYNC\n");
  2273.                 }
  2274.     if (Vm_CopyIn(4, buf, (Address) &flags) != SUCCESS) {
  2275.         Mach_SetErrno(EINVAL);
  2276.         return -1;
  2277.     }
  2278.     if (flags)  {
  2279.         ioctl.command = IOC_SET_BITS;
  2280.     } else {
  2281.         ioctl.command = IOC_CLEAR_BITS;
  2282.     }
  2283.     ioctl.inBufSize = sizeof(int);
  2284.     ioctl.inBuffer = (Address) &flags;
  2285.     flags = IOC_ASYNCHRONOUS;
  2286.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2287.     break;
  2288.  
  2289.     case FIOGETOWN:
  2290.     case SIOCGPGRP:
  2291.     case TIOCGPGRP: {
  2292.         Ioc_Owner owner;
  2293.  
  2294.         if (debugFsStubs) {
  2295.         printf("ioctl: FIOGETOWN\n");
  2296.         }
  2297.         ioctl.command = IOC_GET_OWNER;
  2298.         ioctl.outBuffer = (Address) &owner;
  2299.         ioctl.outBufSize = sizeof(owner);
  2300.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2301.         if (status != SUCCESS) {
  2302.         Mach_SetErrno(Compat_MapCode(status));
  2303.         return -1;
  2304.         }
  2305.         status = Vm_CopyOut(sizeof(int), (Address) &owner.id, buf);
  2306.         if (status != SUCCESS) {
  2307.         Mach_SetErrno(EINVAL);
  2308.         return -1;
  2309.         }
  2310.         }
  2311.         break;
  2312.  
  2313.     case FIOSETOWN:
  2314.     case SIOCSPGRP:
  2315.     case TIOCSPGRP: {
  2316.         Ioc_Owner owner;
  2317.  
  2318.         if (debugFsStubs) {
  2319.                 printf("ioctl: FIOSETOWN\n");
  2320.         }
  2321.         status = Vm_CopyIn(sizeof(int), buf, (Address) &owner.id);
  2322.         if (status != SUCCESS) {
  2323.         Mach_SetErrno(EINVAL);
  2324.         return -1;
  2325.         }
  2326.         owner.procOrFamily = IOC_OWNER_FAMILY;
  2327.         ioctl.command = IOC_SET_OWNER;
  2328.         ioctl.inBuffer = (Address) &owner;
  2329.         ioctl.inBufSize = sizeof(owner);
  2330.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2331.         }
  2332.     break;
  2333.  
  2334.     /* 
  2335.      * Tty-related calls:
  2336.      */
  2337.  
  2338.      case TCGETP:
  2339.      case TIOCGETP: {
  2340.         struct sgttyb temp;
  2341.  
  2342.         if (debugFsStubs) {
  2343.                 printf("ioctl: TIOCGETP\n");
  2344.         }
  2345.         ioctl.command = IOC_TTY_GET_PARAMS;
  2346.         ioctl.outBufSize = sizeof(struct sgttyb);
  2347.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2348.         ioctl.outBuffer = buf;
  2349.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2350.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2351.         } else {
  2352.         ioctl.outBuffer = (Address) &temp;
  2353.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2354.         if (status == SUCCESS) {
  2355.             status = Vm_CopyOut(sizeof(struct sgttyb),
  2356.                             (Address) &temp, buf);
  2357.         }
  2358.         }
  2359.          }
  2360.      break;
  2361.  
  2362.      case TIOCSETP: {
  2363.         struct sgttyb temp;
  2364.  
  2365.         if (debugFsStubs) {
  2366.                 printf("ioctl: TIOCSETP\n");
  2367.         }
  2368.         ioctl.command = IOC_TTY_SET_PARAMS;
  2369.         ioctl.inBufSize = sizeof(struct sgttyb);
  2370.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2371.         ioctl.inBuffer = buf;
  2372.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2373.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2374.         } else {
  2375.         ioctl.inBuffer = (Address) &temp;
  2376.         status = Vm_CopyIn(sizeof(struct sgttyb), buf, (Address) &temp);
  2377.         if (status == SUCCESS) {
  2378.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2379.         }
  2380.         }
  2381.          }
  2382.      break;
  2383.  
  2384.      case TIOCSETN: {
  2385.         struct sgttyb temp;
  2386.  
  2387.         if (debugFsStubs) {
  2388.                 printf("ioctl: TIOCSETN\n");
  2389.         }
  2390.         ioctl.command = IOC_TTY_SETN;
  2391.         ioctl.inBufSize = sizeof(struct sgttyb);
  2392.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2393.         ioctl.inBuffer = buf;
  2394.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2395.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2396.         } else {
  2397.         ioctl.inBuffer = (Address) &temp;
  2398.         status = Vm_CopyIn(sizeof(struct sgttyb), buf, (Address) &temp);
  2399.         if (status == SUCCESS) {
  2400.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2401.         }
  2402.         }
  2403.          }
  2404.      break;
  2405.  
  2406.      case TIOCEXCL:
  2407.     if (debugFsStubs) {
  2408.         printf("ioctl: TIOCEXCL\n");
  2409.     }
  2410.     ioctl.command = IOC_TTY_EXCL;
  2411.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2412.     break;
  2413.  
  2414.      case TIOCNXCL:
  2415.      if (debugFsStubs) {
  2416.          printf("ioctl: TIOCNXCL\n");
  2417.      }
  2418.      ioctl.command = IOC_TTY_NXCL;
  2419.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2420.      break;
  2421.  
  2422.      case TIOCHPCL:
  2423.      if (debugFsStubs) {
  2424.          printf("ioctl: TIOCHPCL\n");
  2425.      }
  2426.      ioctl.command = IOC_TTY_HUP_ON_CLOSE;
  2427.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2428.      break;
  2429.  
  2430.      case TIOCFLUSH: {
  2431.      int temp;
  2432.  
  2433.      if (debugFsStubs) {
  2434.              printf("ioctl: TIOCFLUSH\n");
  2435.          }
  2436.      ioctl.command = IOC_TTY_NXCL;
  2437.      ioctl.inBufSize = sizeof(int);
  2438.      if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM) {
  2439.          ioctl.inBuffer = buf;
  2440.          ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2441.          status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2442.      } else {
  2443.          ioctl.inBuffer = (Address) &temp;
  2444.          status = Vm_CopyIn(sizeof(int), buf, (Address) &temp);
  2445.          if (status == SUCCESS) {
  2446.          status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2447.          }
  2448.      }
  2449.      break;
  2450.          }
  2451.  
  2452.      case TIOCSTI: {
  2453.      int temp;
  2454.  
  2455.      if (debugFsStubs) {
  2456.          printf("ioctl: TIOCSTI\n");
  2457.      }
  2458.      ioctl.command = IOC_TTY_INSERT_CHAR;
  2459.      ioctl.inBufSize = sizeof(int);
  2460.      if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM) {
  2461.          ioctl.inBuffer = buf;
  2462.          ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2463.          status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2464.      } else {
  2465.          ioctl.inBuffer = (Address) &temp;
  2466.          status = Vm_CopyIn(sizeof(int), buf, (Address) &temp);
  2467.          if (status == SUCCESS) {
  2468.          status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2469.          }
  2470.      }
  2471.      }
  2472.      break;
  2473.  
  2474.      case TIOCSBRK:
  2475.          if (debugFsStubs) {
  2476.               printf("ioctl: TIOCSBRK\n");
  2477.          }
  2478.      ioctl.command = IOC_TTY_SET_BREAK;
  2479.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2480.      break;
  2481.  
  2482.      case TIOCCBRK:
  2483.      if (debugFsStubs) {
  2484.              printf("ioctl: TIOCCBRK\n");
  2485.          }
  2486.      ioctl.command = IOC_TTY_CLEAR_BREAK;
  2487.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2488.      break;
  2489.  
  2490.      case TIOCSDTR:
  2491.      if (debugFsStubs) {
  2492.              printf("ioctl: TIOCSDTR\n");
  2493.          }
  2494.      ioctl.command = IOC_TTY_SET_DTR;
  2495.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2496.      break;
  2497.  
  2498.      case TIOCCDTR:
  2499.      if (debugFsStubs) {
  2500.              printf("ioctl: TIOCCDTR\n");
  2501.          }
  2502.      ioctl.command = IOC_TTY_CLEAR_DTR;
  2503.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2504.      break;
  2505.  
  2506.      case TIOCGETC: {
  2507.         struct tchars temp;
  2508.  
  2509.         if (debugFsStubs) {
  2510.         printf("ioctl: TIOCGETC\n");
  2511.         }
  2512.         ioctl.command = IOC_TTY_GET_TCHARS;
  2513.         ioctl.outBufSize = sizeof(struct tchars);
  2514.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2515.         ioctl.outBuffer = buf;
  2516.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2517.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2518.         } else {
  2519.         ioctl.outBuffer = (Address) &temp;
  2520.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2521.         if (status == SUCCESS) {
  2522.             status = Vm_CopyOut(sizeof(struct tchars),
  2523.             (Address) &temp, buf);
  2524.         }
  2525.         }
  2526.          }
  2527.      break;
  2528.  
  2529.      case TIOCSETC: {
  2530.         struct tchars temp;
  2531.  
  2532.         if (debugFsStubs) {
  2533.                 printf("ioctl: TIOCSETC\n");
  2534.             }
  2535.         ioctl.command = IOC_TTY_SET_TCHARS;
  2536.         ioctl.inBufSize = sizeof(struct tchars);
  2537.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2538.         ioctl.inBuffer = buf;
  2539.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2540.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2541.         } else {
  2542.         ioctl.inBuffer = (Address) &temp;
  2543.         status = Vm_CopyIn(sizeof(struct tchars), buf, (Address) &temp);
  2544.         if (status == SUCCESS) {
  2545.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2546.         }
  2547.         }
  2548.          }
  2549.      break;
  2550.  
  2551.      case TIOCGLTC: {
  2552.         struct ltchars temp;
  2553.  
  2554.         if (debugFsStubs) {
  2555.                 printf("ioctl: TIOCGLTC\n");
  2556.             }
  2557.         ioctl.command = IOC_TTY_GET_LTCHARS;
  2558.         ioctl.outBufSize = sizeof(struct ltchars);
  2559.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2560.         ioctl.outBuffer = buf;
  2561.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2562.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2563.         } else {
  2564.         ioctl.outBuffer = (Address) &temp;
  2565.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2566.         if (status == SUCCESS) {
  2567.             status = Vm_CopyOut(sizeof(struct ltchars),
  2568.             (Address) &temp, buf);
  2569.         }
  2570.         }
  2571.          }
  2572.      break;
  2573.  
  2574.      case TIOCSLTC: {
  2575.         struct ltchars temp;
  2576.  
  2577.         if (debugFsStubs) {
  2578.                 printf("ioctl: TIOCSLTC\n");
  2579.             }
  2580.         ioctl.command = IOC_TTY_SET_LTCHARS;
  2581.         ioctl.inBufSize = sizeof(struct ltchars);
  2582.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2583.         ioctl.inBuffer = buf;
  2584.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2585.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2586.         } else {
  2587.         ioctl.inBuffer = (Address) &temp;
  2588.         status = Vm_CopyIn(sizeof(struct ltchars), buf, (Address)&temp);
  2589.         if (status == SUCCESS) {
  2590.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2591.         }
  2592.         }
  2593.         }
  2594.     break;
  2595.  
  2596.      case TIOCLBIS: {
  2597.         int temp;
  2598.  
  2599.         ioctl.command = IOC_TTY_BIS_LM;
  2600.         ioctl.inBufSize = sizeof(int);
  2601.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2602.         ioctl.inBuffer = buf;
  2603.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2604.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2605.         } else {
  2606.         ioctl.inBuffer = (Address) &temp;
  2607.         status = Vm_CopyIn(sizeof(int), buf, (Address) &temp);
  2608.         if (status == SUCCESS) {
  2609.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2610.         }
  2611.         }
  2612.          }
  2613.      break;
  2614.  
  2615.      case TIOCLBIC: {
  2616.         int temp;
  2617.  
  2618.         if (debugFsStubs) {
  2619.                 printf("ioctl: TIOCLBIC\n");
  2620.             }
  2621.         ioctl.command = IOC_TTY_BIC_LM;
  2622.         ioctl.inBufSize = sizeof(int);
  2623.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2624.         ioctl.inBuffer = buf;
  2625.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2626.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2627.         } else {
  2628.         ioctl.inBuffer = (Address) &temp;
  2629.         status = Vm_CopyIn(sizeof(int), buf, (Address) &temp);
  2630.         if (status == SUCCESS) {
  2631.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2632.         }
  2633.         }
  2634.         }
  2635.     break;
  2636.  
  2637.      case TIOCLSET: {
  2638.         int temp;
  2639.  
  2640.         if (debugFsStubs) {
  2641.                 printf("ioctl: TIOCLSET\n");
  2642.             }
  2643.         ioctl.command = IOC_TTY_SET_LM;
  2644.         ioctl.inBufSize = sizeof(int);
  2645.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2646.         ioctl.inBuffer = buf;
  2647.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2648.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2649.         } else {
  2650.         ioctl.inBuffer = (Address) &temp;
  2651.         status = Vm_CopyIn(sizeof(int), buf, (Address) &temp);
  2652.         if (status == SUCCESS) {
  2653.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2654.         }
  2655.         }
  2656.          }
  2657.      break;
  2658.  
  2659.      case TIOCLGET: {
  2660.         int temp;
  2661.  
  2662.         if (debugFsStubs) {
  2663.                 printf("ioctl: TIOCLGET\n");
  2664.             }
  2665.         ioctl.command = IOC_TTY_GET_LM;
  2666.         ioctl.outBufSize = sizeof(int);
  2667.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2668.         ioctl.outBuffer = buf;
  2669.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2670.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2671.         } else {
  2672.         ioctl.outBuffer = (Address) &temp;
  2673.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2674.         if (status == SUCCESS) {
  2675.             status = Vm_CopyOut(sizeof(int), (Address) &temp, buf);
  2676.         }
  2677.         }
  2678.          }
  2679.      break;
  2680.  
  2681.      case TIOCGETD: {
  2682.         int temp;
  2683.  
  2684.         if (debugFsStubs) {
  2685.                 printf("ioctl: TIOCGETD\n");
  2686.             }
  2687.         ioctl.command = IOC_TTY_GET_DISCIPLINE;
  2688.         ioctl.outBufSize = sizeof(int);
  2689.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2690.         ioctl.outBuffer = buf;
  2691.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2692.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2693.         } else {
  2694.         ioctl.outBuffer = (Address) &temp;
  2695.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2696.         if (status == SUCCESS) {
  2697.             status = Vm_CopyOut(sizeof(struct tchars),
  2698.             (Address) &temp, buf);
  2699.         }
  2700.         }
  2701.          }
  2702.      break;
  2703.  
  2704.      case TIOCSETD: {
  2705.         int temp;
  2706.  
  2707.         if (debugFsStubs) {
  2708.                 printf("ioctl: TIOCSETD\n");
  2709.             }
  2710.         ioctl.command = IOC_TTY_SET_DISCIPLINE;
  2711.         ioctl.inBufSize = sizeof(int);
  2712.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2713.         ioctl.inBuffer = buf;
  2714.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2715.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2716.         } else {
  2717.         ioctl.inBuffer = (Address) &temp;
  2718.         status = Vm_CopyIn(sizeof(int), buf, (Address) &temp);
  2719.         if (status == SUCCESS) {
  2720.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2721.         }
  2722.         }
  2723.         }
  2724.     break;
  2725.  
  2726.      case SIOCATMARK: {
  2727.         int temp;
  2728.  
  2729.         if (debugFsStubs) {
  2730.                 printf("ioctl: TIOCATMARK\n");
  2731.             }
  2732.         ioctl.command = IOC_NET_IS_OOB_DATA_NEXT;
  2733.         ioctl.outBufSize = sizeof(int);
  2734.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2735.         ioctl.outBuffer = buf;
  2736.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2737.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2738.         } else {
  2739.         ioctl.outBuffer = (Address) &temp;
  2740.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2741.         if (status == SUCCESS) {
  2742.             status = Vm_CopyOut(sizeof(int), (Address) &temp, buf);
  2743.         }
  2744.         }
  2745.         }
  2746.     break;
  2747.  
  2748.      case TCGETA:
  2749.      case TCGETS: {
  2750.         struct sgttyb ttyb;
  2751.         unsigned int lmode;
  2752.         struct tchars tc;
  2753.         struct ltchars ltc;
  2754.         struct termios ts;
  2755.         struct termio tio;
  2756.  
  2757.         if (debugFsStubs) {
  2758.                 printf("ioctl: TCGETS\n");
  2759.             }
  2760.  
  2761.         status = GetTermInfo(streamPtr, &ioctl, &ttyb, &lmode, &tc, <c);
  2762.         if (status == SUCCESS) {
  2763.         CvtSgttybToTermios(&ttyb, &lmode, &tc, <c, &ts);
  2764.         if (request==TCGETS) {
  2765.             status = Vm_CopyOut(sizeof(struct termios),
  2766.             (Address) &ts, buf);
  2767.         } else {
  2768.             tio.c_iflag = ts.c_iflag;
  2769.             tio.c_oflag = ts.c_oflag;
  2770.             tio.c_cflag = ts.c_cflag;
  2771.             tio.c_lflag = ts.c_lflag;
  2772.             tio.c_line = ts.c_line;
  2773.             bcopy((Address) ts.c_cc, (Address) tio.c_cc, NCC);
  2774.             status = Vm_CopyOut(sizeof(struct termio),
  2775.             (Address) &tio, buf);
  2776.         }
  2777.         }
  2778.         }
  2779.     break;
  2780.  
  2781.      case TCSETA:
  2782.      case TCSETSW:
  2783.      case TCSETSF:
  2784.      case TCSETS: {
  2785.         struct sgttyb ttyb;
  2786.         unsigned int lmode;
  2787.         struct tchars tc;
  2788.         struct ltchars ltc;
  2789.         struct termio tio;
  2790.         struct termios ts;
  2791. #define SETATYPE 0
  2792. #define SETSTYPE 1
  2793.         int type = SETSTYPE;
  2794.         if (request==TCSETA) {
  2795.         type = SETATYPE;
  2796.         }
  2797.  
  2798.         if (debugFsStubs) {
  2799.                 printf("ioctl: TCSETA/S/SW/SF\n");
  2800.             }
  2801.         status = GetTermInfo(streamPtr, &ioctl, &ttyb, &lmode, &tc, <c);
  2802.         if (status != SUCCESS) {
  2803.         Mach_SetErrno(Compat_MapCode(status));
  2804.         return -1;
  2805.         }
  2806.         if (type==SETSTYPE) {
  2807.             status = Vm_CopyIn(sizeof(struct termios),
  2808.             buf, (Address) &ts);
  2809.         } else {
  2810.             status = Vm_CopyIn(sizeof(struct termio),
  2811.             buf, (Address) &tio);
  2812.         ts.c_iflag = tio.c_iflag;
  2813.         ts.c_oflag = tio.c_oflag;
  2814.         ts.c_cflag = tio.c_cflag;
  2815.         ts.c_lflag = tio.c_lflag;
  2816.         ts.c_line = tio.c_line;
  2817.         bzero((Address) ts.c_cc, NCCS);
  2818.         bcopy((Address) tio.c_cc, (Address) ts.c_cc, NCC);
  2819.         }
  2820.         if (status == SUCCESS) {
  2821.         CvtTermiosToSgttyb((type==SETSTYPE)?1:0, &ts, &ttyb,
  2822.             &lmode, &tc, <c);
  2823.         ioctl.command = IOC_TTY_SET_PARAMS;
  2824.         ioctl.inBufSize = sizeof(struct sgttyb);
  2825.         ioctl.inBuffer = (Address) &ttyb;
  2826.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2827.         }
  2828.         if (status == SUCCESS) {
  2829.         ioctl.command = IOC_TTY_SET_LM;
  2830.         ioctl.inBufSize = sizeof(int);
  2831.         ioctl.inBuffer = (Address) &lmode;
  2832.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2833.         }
  2834.         if (status == SUCCESS) {
  2835.         ioctl.command = IOC_TTY_SET_TCHARS;
  2836.         ioctl.inBufSize = sizeof(struct tchars);
  2837.         ioctl.inBuffer = (Address) &tc;
  2838.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2839.         }
  2840.         if (status == SUCCESS) {
  2841.         ioctl.command = IOC_TTY_SET_LTCHARS;
  2842.         ioctl.inBufSize = sizeof(struct ltchars);
  2843.         ioctl.inBuffer = (Address) <c;
  2844.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2845.         }
  2846.         }
  2847.     break;
  2848.  
  2849.      case TIOCGWINSZ: {
  2850.         struct winsize temp;
  2851.  
  2852.         if (debugFsStubs) {
  2853.                 printf("ioctl: TIOCGWINSZ\n");
  2854.         }
  2855.         ioctl.command = IOC_TTY_GET_WINDOW_SIZE;
  2856.         ioctl.outBuffer = (Address) &temp;
  2857.         ioctl.outBufSize = sizeof(struct winsize);
  2858.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2859.         ioctl.outBuffer = buf;
  2860.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2861.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2862.         } else {
  2863.         ioctl.outBuffer = (Address) &temp;
  2864.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2865.         if (status == SUCCESS) {
  2866.             status = Vm_CopyOut(sizeof(struct winsize),
  2867.             (Address) &temp, buf);
  2868.         }
  2869.         }
  2870.         }
  2871.     break;
  2872.  
  2873.      case TIOCSWINSZ: {
  2874.         struct winsize temp;
  2875.  
  2876.         if (debugFsStubs) {
  2877.                 printf("ioctl: TIOCSWINSZ\n");
  2878.         }
  2879.         ioctl.command = IOC_TTY_SET_WINDOW_SIZE;
  2880.         ioctl.inBufSize = sizeof(struct winsize);
  2881.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2882.         ioctl.inBuffer = buf;
  2883.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2884.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2885.         } else {
  2886.         ioctl.inBuffer = (Address) &temp;
  2887.             status = Vm_CopyIn(sizeof(struct winsize),
  2888.             buf, (Address) &temp);
  2889.         if (status == SUCCESS) {
  2890.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2891.         }
  2892.         }
  2893.          }
  2894.      break;
  2895.  
  2896.     /*
  2897.      * Graphics requests.
  2898.      */
  2899.  
  2900.      case QIOCGINFO: {
  2901.         DevScreenInfo *temp;
  2902.  
  2903.         if (debugFsStubs) {
  2904.                 printf("ioctl: QIOCGINFO\n");
  2905.         }
  2906.         ioctl.command = IOC_GRAPHICS_GET_INFO;
  2907.         ioctl.outBufSize = sizeof(DevScreenInfo *);
  2908.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2909.         ioctl.outBuffer = buf;
  2910.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2911.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2912.         } else {
  2913.         ioctl.outBuffer = (Address) &temp;
  2914.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2915.         if (status == SUCCESS) {
  2916.             status = Vm_CopyOut(sizeof(DevScreenInfo *),
  2917.             (Address) &temp, buf);
  2918.         }
  2919.         }
  2920.         }
  2921.     break;
  2922.  
  2923.      case QIOCPMSTATE: {
  2924.         DevCursor temp;
  2925.  
  2926.         if (debugFsStubs) {
  2927.                 printf("ioctl: QIOCPMSTATE\n");
  2928.         }
  2929.         ioctl.command = IOC_GRAPHICS_MOUSE_POS;
  2930.         ioctl.outBufSize = sizeof(DevCursor);
  2931.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2932.         ioctl.outBuffer = buf;
  2933.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2934.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2935.         } else {
  2936.         ioctl.outBuffer = (Address) &temp;
  2937.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2938.         if (status == SUCCESS) {
  2939.             status = Vm_CopyOut(sizeof(DevCursor),
  2940.             (Address) &temp, buf);
  2941.         }
  2942.         }
  2943.         }
  2944.     break;
  2945.  
  2946.      case QIOWCURSORCOLOR: {
  2947.         unsigned int temp[6];
  2948.  
  2949.         if (debugFsStubs) {
  2950.                 printf("ioctl: QIOWCURSORCOLOR\n");
  2951.         }
  2952.         ioctl.command = IOC_GRAPHICS_CURSOR_COLOR;
  2953.         ioctl.inBufSize = sizeof(unsigned int [6]);
  2954.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2955.         ioctl.inBuffer = buf;
  2956.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2957.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2958.         } else {
  2959.         ioctl.inBuffer = (Address) temp;
  2960.         status = Vm_CopyIn(sizeof(unsigned int [6]),
  2961.             buf, (Address) temp);
  2962.         if (status == SUCCESS) {
  2963.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2964.         }
  2965.         }
  2966.          }
  2967.      break;
  2968.  
  2969.      case QIOCINIT:
  2970.      if (debugFsStubs) {
  2971.          printf("ioctl: QIOCINIT\n");
  2972.      }
  2973.      ioctl.command = IOC_GRAPHICS_INIT_SCREEN;
  2974.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2975.      break;
  2976.  
  2977.      case QIOCKPCMD: {
  2978.          DevKpCmd temp;
  2979.  
  2980.          if (debugFsStubs) {
  2981.                 printf("ioctl: QIOCKPCMD\n");
  2982.              }
  2983.          ioctl.command = IOC_GRAPHICS_KBD_CMD;
  2984.          ioctl.inBufSize = sizeof(DevKpCmd);
  2985.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2986.         ioctl.inBuffer = buf;
  2987.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2988.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2989.         } else {
  2990.         ioctl.inBuffer = (Address) &temp;
  2991.         status = Vm_CopyIn(sizeof(DevKpCmd), buf, (Address) &temp);
  2992.         if (status == SUCCESS) {
  2993.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2994.         }
  2995.         }
  2996.          }
  2997.      break;
  2998.  
  2999.      case QIOCADDR: {
  3000.         DevScreenInfo *temp;
  3001.  
  3002.         if (debugFsStubs) {
  3003.                 printf("ioctl: QIOCADDR\n");
  3004.             }
  3005.         ioctl.command = IOC_GRAPHICS_GET_INFO_ADDR;
  3006.         ioctl.outBufSize = sizeof(DevScreenInfo *);
  3007.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  3008.         ioctl.outBuffer = buf;
  3009.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  3010.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3011.         } else {
  3012.         ioctl.outBuffer = (Address) &temp;
  3013.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3014.         if (status == SUCCESS) {
  3015.             status = Vm_CopyOut(sizeof(DevScreenInfo *),
  3016.             (Address) &temp, buf);
  3017.         }
  3018.         }
  3019.         }
  3020.     break;
  3021.  
  3022.      case QIOWCURSOR: {
  3023.         short temp[32];
  3024.  
  3025.         if (debugFsStubs) {
  3026.                 printf("ioctl: QIOWCURSOR\n");
  3027.         }
  3028.         ioctl.command = IOC_GRAPHICS_CURSOR_BIT_MAP;
  3029.         ioctl.inBufSize = sizeof(short[32]);
  3030.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  3031.         ioctl.inBuffer = buf;
  3032.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  3033.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3034.         } else {
  3035.         ioctl.inBuffer = (Address) temp;
  3036.         status = Vm_CopyIn(sizeof(temp), buf, (Address) temp);
  3037.         if (status == SUCCESS) {
  3038.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3039.         }
  3040.         }
  3041.         }
  3042.     break;
  3043.  
  3044.      case QIOKERNLOOP:
  3045.      if (debugFsStubs) {
  3046.                 printf("ioctl: QIOKERNLOOP\n");
  3047.      }
  3048.      ioctl.command = IOC_GRAPHICS_KERN_LOOP;
  3049.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3050.      break;
  3051.  
  3052.      case QIOKERNUNLOOP:
  3053.      if (debugFsStubs) {
  3054.                 printf("ioctl: QIOKERNUNLOOP\n");
  3055.      }
  3056.      ioctl.command = IOC_GRAPHICS_KERN_UNLOOP;
  3057.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3058.      break;
  3059.  
  3060.      case QIOVIDEOON:
  3061.      if (debugFsStubs) {
  3062.                 printf("ioctl: QIOVIDEOON\n");
  3063.      }
  3064.      ioctl.command = IOC_GRAPHICS_VIDEO_ON;
  3065.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3066.      break;
  3067.  
  3068.      case QIOVIDEOOFF:
  3069.      if (debugFsStubs) {
  3070.                 printf("ioctl: QIOVIDEOOFF\n");
  3071.      }
  3072.      ioctl.command = IOC_GRAPHICS_VIDEO_OFF;
  3073.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3074.      break;
  3075.  
  3076.      case QIOSETCMAP: {
  3077.         DevColorMap temp;
  3078.  
  3079.         if (debugFsStubs) {
  3080.                 printf("ioctl: QIOSETCMAP\n");
  3081.         }
  3082.         ioctl.command = IOC_GRAPHICS_COLOR_MAP;
  3083.         ioctl.inBufSize = sizeof(DevColorMap);
  3084.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  3085.         ioctl.inBuffer = buf;
  3086.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  3087.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3088.         } else {
  3089.         ioctl.inBuffer = (Address) &temp;
  3090.         status = Vm_CopyIn(sizeof(temp), buf, (Address) &temp);
  3091.         if (status == SUCCESS) {
  3092.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3093.         }
  3094.         }
  3095.         }
  3096.     break;
  3097.  
  3098.       case SIOCGIFCONF: {
  3099.       /*
  3100.        * Fake the ifconfig ioctl.  This is a hack done for X.  
  3101.        * A more general implementation is probably needed.
  3102.        */
  3103.       struct ifconf ifc;
  3104.       struct ifreq   ifreq;
  3105.       Net_Interface      *interPtr;
  3106.  
  3107.       if (debugFsStubs) {
  3108.                 printf("ioctl: SIOCGIFCONF\n");
  3109.       }
  3110.       status = Vm_CopyIn(sizeof(struct ifconf), buf, (Address)&ifc);
  3111.       if (status != SUCCESS) {
  3112.           return(status);
  3113.       }
  3114.  
  3115.       if (ifc.ifc_len < 32) {
  3116.           status = SYS_INVALID_ARG;
  3117.           break;
  3118.       }
  3119.       /*
  3120.        * We give a length of 32 and put in the request buffer 
  3121.        * the name ("se0"), followed by the family (AF_INET), 
  3122.        * and finally our internet address.
  3123.        */
  3124.       ifc.ifc_len = 32;
  3125.       interPtr = Net_GetInterface(NET_NETWORK_ETHER, 0);
  3126.       if (interPtr == NULL) {
  3127.           return FAILURE;
  3128.       }
  3129.       if (!strcmp(interPtr->name, "LE")) {
  3130.           (void) strcpy(ifreq.ifr_name, "le0");
  3131.       } else if (!strcmp(interPtr->name, "IE")) {
  3132.           (void) strcpy(ifreq.ifr_name, "ie0");
  3133.       }
  3134.       ifreq.ifr_addr.sa_family = AF_INET;
  3135.       /*
  3136.        * I'm not sure how to cast the sa_data field properly, but
  3137.        * sunos returns the IP address starting in the third byte
  3138.        * of the field.  Without the cast it's kind of brute force.
  3139.        */
  3140.  
  3141.       * ((int *) &ifreq.ifr_addr.sa_data[2]) = 
  3142.           (int) interPtr->netAddress[NET_PROTO_INET].address.inet;
  3143.       status = Vm_CopyOut(sizeof(struct ifconf), (Address)&ifc, buf);
  3144.       status = Vm_CopyOut(32, (Address)&ifreq,
  3145.           (Address)ifc.ifc_ifcu.ifcu_req);
  3146.       }
  3147.       break;
  3148.  
  3149.       case SIOCRPHYSADDR: {
  3150.         /* Get the ethernet address. */
  3151.  
  3152.         struct ifdevea *p;
  3153.         Net_EtherAddress etherAddress;
  3154.  
  3155.         if (debugFsStubs) {
  3156.         printf("ioctl: SIOCRPHYSADDR\n");
  3157.         }
  3158.         Mach_GetEtherAddress(ðerAddress);
  3159.         p = (struct ifdevea *) buf;
  3160.           p->default_pa[0] = p->current_pa[0] = etherAddress.byte1;
  3161.           p->default_pa[1] = p->current_pa[1] = etherAddress.byte2;
  3162.           p->default_pa[2] = p->current_pa[2] = etherAddress.byte3;
  3163.           p->default_pa[3] = p->current_pa[3] = etherAddress.byte4;
  3164.           p->default_pa[4] = p->current_pa[4] = etherAddress.byte5;
  3165.           p->default_pa[5] = p->current_pa[5] = etherAddress.byte6;
  3166.           status = SUCCESS;
  3167.          }
  3168.      break;
  3169.  
  3170.     case SIOCGIFFLAGS: {
  3171.       struct ifreq   ifreq;
  3172.  
  3173.       if (debugFsStubs) {
  3174.                 printf("ioctl: SIOCGIFFLAGS\n");
  3175.       }
  3176.       status = Vm_CopyIn(sizeof(struct ifreq), buf, (Address)&ifreq);
  3177.       if (status != SUCCESS) {
  3178.           return(status);
  3179.       }
  3180.       ifreq.ifr_flags = IFF_UP | IFF_RUNNING;
  3181.       status = Vm_CopyOut(sizeof(struct ifreq), (Address)&ifreq, buf);
  3182.     }
  3183.     break;
  3184.  
  3185.      default:
  3186.     /*
  3187.      * This code is for debugging, to make it easy to figure
  3188.      * out what ioctl is unimplemented.
  3189.      * It can be removed when ioctl development is reasonably
  3190.      * complete.
  3191.      */
  3192.     if ((request&IOC_DIRMASK)==IOC_VOID) {
  3193.         printf("Bad Ioctl: _IO(%c,%d)\n", (request>>8)&0xff,
  3194.             request&0xff);
  3195.     } else if ((request&IOC_DIRMASK)==IOC_OUT) {
  3196.         printf("Bad Ioctl: _IOR(%c,%d,%d)\n", (request>>8)&0xff,
  3197.             request&0xff, IOCPARM_LEN(request));
  3198.     } else if ((request&IOC_DIRMASK)==IOC_IN) {
  3199.         printf("Bad Ioctl: _IOW(%c,%d,%d)\n", (request>>8)&0xff,
  3200.             request&0xff, IOCPARM_LEN(request));
  3201.     } else if ((request&IOC_DIRMASK)==IOC_INOUT) {
  3202.         printf("Bad Ioctl: _IOWR(%c,%d,%d)\n", (request>>8)&0xff,
  3203.             request&0xff, IOCPARM_LEN(request));
  3204.     } else {
  3205.         printf("Bad Ioctl: 0x%08x\n",request);
  3206.     }
  3207.     Mach_SetErrno(EINVAL);
  3208.     return -1;
  3209.     }
  3210.     if (status != SUCCESS) {
  3211.     Mach_SetErrno(Compat_MapCode(status));
  3212.     return -1;
  3213.     }        
  3214.     return 0;
  3215. }
  3216.  
  3217.  
  3218.  
  3219. /*
  3220.  *----------------------------------------------------------------------
  3221.  *
  3222.  * Fs_NewRenameStub --
  3223.  *
  3224.  *    The stub for the "newrename" Unix system call.
  3225.  *
  3226.  * Results:
  3227.  *    Returns -1 on failure.
  3228.  *
  3229.  * Side effects:
  3230.  *    Side effects associated with the system call.
  3231.  *     
  3232.  *
  3233.  *----------------------------------------------------------------------
  3234.  */
  3235. int
  3236. Fs_NewRenameStub(pathName, newName)
  3237.     char *pathName;
  3238.     char *newName;
  3239. {
  3240.     ReturnStatus    status;
  3241.     int            pathNameLength;
  3242.     int            newNameLength;
  3243.     char        newPathName[FS_MAX_PATH_NAME_LENGTH];
  3244.     char        *newNewName;
  3245.  
  3246.     if (debugFsStubs) {
  3247.     printf("Fs_RenameStub\n");
  3248.     }
  3249.     /*
  3250.      * Copy the name in from user space onto the kernel stack.
  3251.      */
  3252.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newPathName,
  3253.                &pathNameLength) != SUCCESS) {
  3254.     Mach_SetErrno(EACCES);
  3255.     return -1;
  3256.     }
  3257.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  3258.     Mach_SetErrno(EINVAL);
  3259.     return -1;
  3260.     }
  3261.  
  3262.     /*
  3263.      * Maybe I could put the new name onto the stack as well but I am 
  3264.      * allocing it here because I'm not sure if the stack is big enough.
  3265.      * Should just make the stack bigger I suppose ...
  3266.      */
  3267.     newNewName = (char  *) malloc(FS_MAX_PATH_NAME_LENGTH);
  3268.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, newName, newNewName,
  3269.                &newNameLength) == SUCCESS) {
  3270.     if (newNameLength == FS_MAX_PATH_NAME_LENGTH) {
  3271.         status = FS_INVALID_ARG;
  3272.     } else {
  3273.         status = Fs_Rename(newPathName, newNewName);
  3274.     }
  3275.     } else {
  3276.     status = SYS_ARG_NOACCESS;
  3277.     }
  3278.     free((Address) newNewName);
  3279.     if (status != SUCCESS) {
  3280.     Mach_SetErrno(Compat_MapCode(status));
  3281.     return -1;
  3282.     }
  3283.     return 0;
  3284. }
  3285.  
  3286.  
  3287. /*
  3288.  *----------------------------------------------------------------------
  3289.  *
  3290.  * Fs_FtruncateStub --
  3291.  *
  3292.  *    The stub for the "ftruncate" Unix system call.
  3293.  *
  3294.  * Results:
  3295.  *    Returns -1 on failure.
  3296.  *
  3297.  * Side effects:
  3298.  *    Side effects associated with the system call.
  3299.  *     
  3300.  *
  3301.  *----------------------------------------------------------------------
  3302.  */
  3303. int
  3304. Fs_FtruncateStub(streamID, length)
  3305.     int streamID;
  3306.     unsigned long length;
  3307. {
  3308.     ReturnStatus        status;
  3309.     Proc_ControlBlock   *procPtr;
  3310.     Fs_Stream             *streamPtr;
  3311.     Fs_IOCParam         ioctl;
  3312.     Fs_IOReply          reply;
  3313.  
  3314.     if (debugFsStubs) {
  3315.     printf("Fs_FtruncateStub\n");
  3316.     }
  3317.     procPtr = Proc_GetEffectiveProc();
  3318.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  3319.     ioctl.command = IOC_TRUNCATE;
  3320.     ioctl.format = mach_Format;
  3321.     ioctl.procID = procPtr->processID;
  3322.     ioctl.familyID = procPtr->familyID;
  3323.     ioctl.uid = procPtr->effectiveUserID;
  3324.     ioctl.flags = 0;
  3325.     ioctl.outBuffer = 0;
  3326.     ioctl.outBufSize = 0;
  3327.     ioctl.inBuffer = (Address) &length;
  3328.     ioctl.inBufSize = sizeof(length);
  3329.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3330.     if (status != SUCCESS) {
  3331.     Mach_SetErrno(Compat_MapCode(status));
  3332.     return -1;
  3333.     }
  3334.     return 0;
  3335. }
  3336.  
  3337. /*
  3338.  *----------------------------------------------------------------------
  3339.  *
  3340.  * Fs_TruncateStub --
  3341.  *
  3342.  *    The stub for the "truncate" Unix system call.
  3343.  *
  3344.  * Results:
  3345.  *    Returns -1 on failure.
  3346.  *
  3347.  * Side effects:
  3348.  *    Side effects associated with the system call.
  3349.  *     
  3350.  *
  3351.  *----------------------------------------------------------------------
  3352.  */
  3353. int
  3354. Fs_TruncateStub(path, length)
  3355.     char *path;
  3356.     unsigned long length;
  3357. {
  3358.     int    streamID;
  3359.     int status;
  3360.  
  3361.     if (debugFsStubs) {
  3362.     printf("Fs_TruncateStub\n");
  3363.     }
  3364.     streamID = Fs_NewOpenStub(path, FS_WRITE, 0);
  3365.     if (streamID == -1) {
  3366.     return -1;
  3367.     }
  3368.     status = Fs_FtruncateStub(streamID, length);
  3369.     (void) Fs_UserClose(streamID);
  3370.     return status;
  3371. }
  3372.  
  3373. /*
  3374.  *----------------------------------------------------------------------
  3375.  *
  3376.  * Fs_FlockStub --
  3377.  *
  3378.  *    The stub for the "flock" Unix system call.
  3379.  *
  3380.  * Results:
  3381.  *    Returns -1 on failure.
  3382.  *
  3383.  * Side effects:
  3384.  *    Side effects associated with the system call.
  3385.  *     
  3386.  *
  3387.  *----------------------------------------------------------------------
  3388.  */
  3389. int
  3390. Fs_FlockStub(streamID, operation)
  3391.     int    streamID;
  3392.     int operation;
  3393. {
  3394.     ReturnStatus status;
  3395.     Ioc_LockArgs args;
  3396.     Proc_ControlBlock   *procPtr;
  3397.     Fs_Stream             *streamPtr;
  3398.     Fs_IOCParam         ioctl;
  3399.     Fs_IOReply          reply;
  3400.  
  3401.     if (debugFsStubs) {
  3402.     printf("Fs_FlockStub\n");
  3403.     }
  3404.     args.flags = 0;
  3405.     if (operation & LOCK_EX) {
  3406.     args.flags |= IOC_LOCK_EXCLUSIVE;
  3407.     } else if (operation & LOCK_SH) {
  3408.     args.flags |= IOC_LOCK_SHARED;
  3409.     }
  3410.     if (operation & LOCK_NB) {
  3411.     args.flags |= IOC_LOCK_NO_BLOCK;
  3412.     }
  3413.     procPtr = Proc_GetEffectiveProc();
  3414.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  3415.     if (operation & LOCK_UN) {
  3416.     ioctl.command = IOC_UNLOCK;
  3417.     } else {
  3418.     ioctl.command = IOC_LOCK;
  3419.     }
  3420.     ioctl.format = mach_Format;
  3421.     ioctl.procID = procPtr->processID;
  3422.     ioctl.familyID = procPtr->familyID;
  3423.     ioctl.uid = procPtr->effectiveUserID;
  3424.     ioctl.flags = 0;
  3425.     ioctl.outBuffer = 0;
  3426.     ioctl.outBufSize = 0;
  3427.     ioctl.inBuffer = (Address) &args;
  3428.     ioctl.inBufSize = sizeof(Ioc_LockArgs),
  3429.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3430.     if (status != SUCCESS) {
  3431.     Mach_SetErrno(Compat_MapCode(status));
  3432.     return -1;
  3433.     }
  3434.     return 0;
  3435. }
  3436.  
  3437.  
  3438. /*
  3439.  *----------------------------------------------------------------------
  3440.  *
  3441.  * Fs_MkdirStub --
  3442.  *
  3443.  *    The stub for the "mkdir" Unix system call.
  3444.  *
  3445.  * Results:
  3446.  *    Returns -1 on failure.
  3447.  *
  3448.  * Side effects:
  3449.  *    Side effects associated with the system call.
  3450.  *     
  3451.  *
  3452.  *----------------------------------------------------------------------
  3453.  */
  3454. int
  3455. Fs_MkdirStub(pathName, permissions)
  3456.     char *pathName;        /* The name of the directory to create */
  3457.     int permissions;        /* Permission mask to use on creation */
  3458. {
  3459.     ReturnStatus        status;
  3460.     int            pathNameLength;
  3461.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  3462.  
  3463.     if (debugFsStubs) {
  3464.     printf("Fs_MkdirStub\n");
  3465.     }
  3466.     /*
  3467.      * Copy the name in from user space to the kernel stack.
  3468.      */
  3469.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  3470.                &pathNameLength) != SUCCESS) {
  3471.     Mach_SetErrno(EACCES);
  3472.     return -1;
  3473.     }
  3474.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  3475.     Mach_SetErrno(EINVAL);
  3476.     return -1;
  3477.     }
  3478.     status = Fs_MakeDir(newName, permissions);
  3479.     if (status != SUCCESS) {
  3480.     Mach_SetErrno(Compat_MapCode(status));
  3481.     return -1;
  3482.     }
  3483.     return 0;
  3484. }
  3485.  
  3486. /*
  3487.  *----------------------------------------------------------------------
  3488.  *
  3489.  * Fs_RmdirStub --
  3490.  *
  3491.  *    The stub for the "rmdir" Unix system call.
  3492.  *
  3493.  * Results:
  3494.  *    Returns -1 on failure.
  3495.  *
  3496.  * Side effects:
  3497.  *    Side effects associated with the system call.
  3498.  *     
  3499.  *
  3500.  *----------------------------------------------------------------------
  3501.  */
  3502. int
  3503. Fs_RmdirStub(pathName)
  3504.     char *pathName;        /* The name of the directory to create */
  3505. {
  3506.     ReturnStatus    status;
  3507.     int            pathNameLength;
  3508.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  3509.  
  3510.     if (debugFsStubs) {
  3511.     printf("Fs_RmdirStub\n");
  3512.     }
  3513.     /*
  3514.      * Copy the name in from user space onto the kernel stack.
  3515.      */
  3516.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  3517.                &pathNameLength) != SUCCESS) {
  3518.     Mach_SetErrno(EACCES);
  3519.     return -1;
  3520.     }
  3521.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  3522.     Mach_SetErrno(EINVAL);
  3523.     return -1;
  3524.     }
  3525.     status = Fs_RemoveDir(newName);
  3526.     if (status != SUCCESS) {
  3527.     Mach_SetErrno(Compat_MapCode(status));
  3528.     return -1;
  3529.     }
  3530.     return 0;
  3531. }
  3532.  
  3533. /*
  3534.  *----------------------------------------------------------------------
  3535.  *
  3536.  * Fs_UtimesStub --
  3537.  *
  3538.  *    The stub for the "utimes" Unix system call.
  3539.  *
  3540.  * Results:
  3541.  *    Returns -1 on failure.
  3542.  *
  3543.  * Side effects:
  3544.  *    Side effects associated with the system call.
  3545.  *     
  3546.  *
  3547.  *----------------------------------------------------------------------
  3548.  */
  3549. int
  3550. Fs_UtimesStub(pathName, tvp)
  3551.     char    *pathName;
  3552.     struct timeval *tvp;
  3553. {
  3554.     ReturnStatus    status;
  3555.     Fs_Attributes   attributes;
  3556.     int            pathNameLength;
  3557.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  3558.     struct timeval  tv[2];
  3559.  
  3560.     if (debugFsStubs) {
  3561.     printf("Fs_Utimes\n");
  3562.     }
  3563.  
  3564.     if (Vm_CopyIn(sizeof(tv), (Address) tvp, (Address) tv) != SUCCESS) {
  3565.     Mach_SetErrno(EFAULT);
  3566.     return -1;
  3567.     }
  3568.     attributes.accessTime.seconds = tv[0].tv_sec;
  3569.     attributes.accessTime.microseconds = tv[0].tv_usec;
  3570.     attributes.dataModifyTime.seconds = tv[1].tv_sec;
  3571.     attributes.dataModifyTime.microseconds = tv[1].tv_usec;
  3572.  
  3573.     /*
  3574.      * Copy the name in from user space onto the kernel stack.
  3575.      */
  3576.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  3577.                &pathNameLength) != SUCCESS) {
  3578.         Mach_SetErrno(EACCES);
  3579.     return -1;
  3580.     }
  3581.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  3582.     Mach_SetErrno(EINVAL);
  3583.     return -1;
  3584.     }
  3585.     status = Fs_SetAttributes(newName,
  3586.                           FS_ATTRIB_FILE, &attributes, FS_SET_TIMES);
  3587.     if (status != SUCCESS) {
  3588.     Mach_SetErrno(Compat_MapCode(status));
  3589.     return -1;
  3590.     }
  3591.     return 0;
  3592. }
  3593.  
  3594. /*
  3595.  *----------------------------------------------------------------------
  3596.  *
  3597.  * Fs_SyncStub --
  3598.  *
  3599.  *    The stub for the "sync" Unix system call.
  3600.  *
  3601.  * Results:
  3602.  *    Returns -1 on failure.
  3603.  *
  3604.  * Side effects:
  3605.  *    Side effects associated with the system call.
  3606.  *     
  3607.  *
  3608.  *----------------------------------------------------------------------
  3609.  */
  3610. int
  3611. Fs_SyncStub()
  3612. {
  3613.  
  3614.     printf("Fs_SyncStub is not implemented\n");
  3615.     Mach_SetErrno(EINVAL);
  3616.     return -1;
  3617. }
  3618.  
  3619. /*
  3620.  *----------------------------------------------------------------------
  3621.  *
  3622.  * Fs_GetdtablesizeStub --
  3623.  *
  3624.  *    The stub for the "getdtablesize" Unix system call.
  3625.  *
  3626.  * Results:
  3627.  *    Returns -1 on failure.
  3628.  *
  3629.  * Side effects:
  3630.  *    Side effects associated with the system call.
  3631.  *     
  3632.  *
  3633.  *----------------------------------------------------------------------
  3634.  */
  3635. int 
  3636. Fs_GetdtablesizeStub()
  3637. {
  3638.  
  3639.     if (debugFsStubs) {
  3640.     printf("Fs_GetdtablesizeStub\n");
  3641.     }
  3642.     return 100;
  3643. }
  3644.  
  3645. /*
  3646.  *----------------------------------------------------------------------
  3647.  *
  3648.  * Fs_GetdoptStub --
  3649.  *
  3650.  *    The stub for the "getdopt" Unix system call.
  3651.  *
  3652.  * Results:
  3653.  *    Returns -1 on failure.
  3654.  *
  3655.  * Side effects:
  3656.  *    Side effects associated with the system call.
  3657.  *     
  3658.  *
  3659.  *----------------------------------------------------------------------
  3660.  */
  3661. int
  3662. Fs_GetdoptStub()
  3663.  
  3664. {
  3665.  
  3666.     printf("getdopt is not implemented\n");
  3667.     Mach_SetErrno(EINVAL);
  3668.     return -1;
  3669. }
  3670.  
  3671. /*
  3672.  *----------------------------------------------------------------------
  3673.  *
  3674.  * Fs_SetdoptStub --
  3675.  *
  3676.  *    The stub for the "setdopt" Unix system call.
  3677.  *
  3678.  * Results:
  3679.  *    Returns -1 on failure.
  3680.  *
  3681.  * Side effects:
  3682.  *    Side effects associated with the system call.
  3683.  *     
  3684.  *
  3685.  *----------------------------------------------------------------------
  3686.  */
  3687. int
  3688. Fs_SetdoptStub()
  3689. {
  3690.  
  3691.     printf("setdopt is not implemented\n");
  3692.     Mach_SetErrno(EINVAL);
  3693.     return -1;
  3694. }
  3695.  
  3696. /*
  3697.  *----------------------------------------------------------------------
  3698.  *
  3699.  * Fs_FcntlStub --
  3700.  *
  3701.  *    The stub for the "fcntl" Unix system call.
  3702.  *
  3703.  * Results:
  3704.  *    Returns -1 on failure.
  3705.  *
  3706.  * Side effects:
  3707.  *    Side effects associated with the system call.
  3708.  *     
  3709.  *
  3710.  *----------------------------------------------------------------------
  3711.  */
  3712. int
  3713. Fs_FcntlStub(fd, cmd, arg)
  3714. int fd, cmd, arg;
  3715. {
  3716.  
  3717.     Proc_ControlBlock *procPtr=Proc_GetEffectiveProc();
  3718.     Fs_Stream *streamPtr;
  3719.     ReturnStatus status;
  3720.     int value;
  3721.     Address        usp;
  3722.  
  3723.     if (debugFsStubs) {
  3724.     printf("Fs_FcntlStub(%d, %d, %d)\n", fd, cmd, arg);
  3725.     }
  3726.  
  3727.     status = Fs_GetStreamPtr(procPtr, fd, &streamPtr);
  3728.     if (status != SUCCESS) {
  3729.     Mach_SetErrno(EBADF);
  3730.     return -1;
  3731.     }
  3732.  
  3733.     usp = Mach_UserStack();
  3734.  
  3735.     switch (cmd) {
  3736.     case F_DUPFD:
  3737.         value = arg;
  3738.         status = Fs_GetNewID(fd, (int *)&value);
  3739.         if (status == SUCCESS) {
  3740.         return value;
  3741.         }
  3742.         break;
  3743.  
  3744.     case F_GETFD:
  3745.         usp -= sizeof(int);
  3746.         status = Fs_IOControlStub(fd, IOC_GET_FLAGS, 
  3747.                 0, (Address) NULL, sizeof(value), usp);
  3748.         if (status == SUCCESS) {
  3749.         (void)Vm_CopyIn(sizeof(int), (Address)usp, (Address)value);
  3750.         return (value & IOC_CLOSE_ON_EXEC) ? 1 : 0;
  3751.         }
  3752.         break;
  3753.  
  3754.     case F_SETFD:
  3755.         usp -= sizeof(int);
  3756.         value = IOC_CLOSE_ON_EXEC;
  3757.         status = Vm_CopyOut(sizeof(value), (Address)&value, usp);
  3758.         if (status != SUCCESS) {
  3759.         break;
  3760.         }
  3761.         if (arg & 1) {
  3762.         status = Fs_IOControlStub(fd, IOC_SET_BITS, 
  3763.                 sizeof(value), usp, 0, (Address) NULL);
  3764.         } else {
  3765.         status = Fs_IOControlStub(fd, IOC_CLEAR_BITS, 
  3766.                 sizeof(value), usp, 0, (Address) NULL);
  3767.         }
  3768.         if (status == SUCCESS) {
  3769.         return 0;
  3770.         }
  3771.         break;
  3772.  
  3773.     case F_GETFL:  {
  3774.         int temp, returnValue;
  3775.  
  3776.         usp -= sizeof(int);
  3777.         status = Fs_IOControlStub(fd, IOC_GET_FLAGS, 
  3778.                 0, (Address) NULL, sizeof(temp), usp);
  3779.         if (status != SUCCESS) {
  3780.             break;
  3781.         }
  3782.  
  3783.         returnValue = 0;
  3784.  
  3785.         (void)Vm_CopyIn(sizeof(temp), usp, (Address)&temp);
  3786.         if (temp & IOC_APPEND) {
  3787.             returnValue |= FAPPEND;
  3788.         }
  3789.         if (temp & IOC_NON_BLOCKING) {
  3790.             returnValue |= FNDELAY;
  3791.         }
  3792.         if (temp & IOC_ASYNCHRONOUS) {
  3793.             returnValue |= FASYNC;
  3794.         }
  3795.         return returnValue;
  3796.         }
  3797.         break;
  3798.  
  3799.     case F_SETFL:
  3800.         value = 0;
  3801.         if (arg & FAPPEND) {
  3802.         value |= IOC_APPEND;
  3803.         }
  3804.         if (arg & FNDELAY) {
  3805.         value |= IOC_NON_BLOCKING;
  3806.         }
  3807.         if (arg & FASYNC) {
  3808.         value |= IOC_ASYNCHRONOUS;
  3809.         }
  3810.         if (value == 0) {
  3811.         status = SUCCESS;
  3812.         } else {
  3813.         usp -= sizeof(int);
  3814.         status = Vm_CopyOut(sizeof(value), (Address)&value, usp);
  3815.         if (status != SUCCESS) {
  3816.             break;
  3817.         }
  3818.         status = Fs_IOControlStub(fd, IOC_SET_BITS, 
  3819.                 sizeof(value), usp, 0, (Address) NULL);
  3820.         }
  3821.         if (status == SUCCESS) {
  3822.         return 0;
  3823.         }
  3824.         break;
  3825.  
  3826.     case F_GETOWN: {
  3827.         Ioc_Owner owner;
  3828.  
  3829.         usp -= sizeof(owner);
  3830.         status = Fs_IOControlStub(fd, IOC_GET_OWNER, 
  3831.                       0, (Address) NULL,
  3832.                       sizeof(owner), usp);
  3833.         if (status != SUCCESS) {
  3834.             break;
  3835.         }
  3836.         (void)Vm_CopyIn(sizeof(owner), (Address)usp, (Address)&owner);
  3837.         if (owner.procOrFamily == IOC_OWNER_FAMILY) {
  3838.             return -owner.id;
  3839.         } else {
  3840.             return owner.id;
  3841.         }
  3842.         }
  3843.         break;
  3844.  
  3845.     case F_SETOWN: {
  3846.         Ioc_Owner owner;
  3847.  
  3848.         usp -= sizeof(owner);
  3849.         if (arg < 0) {
  3850.             owner.id = -arg;
  3851.             owner.procOrFamily = IOC_OWNER_FAMILY;
  3852.         } else {
  3853.             owner.id = arg;
  3854.             owner.procOrFamily = IOC_OWNER_PROC;
  3855.         }
  3856.         status = Vm_CopyOut(sizeof(owner), (Address)&owner, usp);
  3857.         if (status != SUCCESS) {
  3858.             break;
  3859.         }
  3860.         status = Fs_IOControlStub(fd, IOC_SET_OWNER, 
  3861.                 sizeof(owner), usp, 0, (Address) NULL);
  3862.         if (status == SUCCESS) {
  3863.             return 0;
  3864.         }
  3865.             
  3866.         }
  3867.         break;
  3868.  
  3869.     default:
  3870.         printf("Unimplemented fcntl function %d\n", cmd);
  3871.         Mach_SetErrno(EINVAL);
  3872.         return -1;
  3873.         break;
  3874.     }
  3875.  
  3876.     Mach_SetErrno(Compat_MapCode(status));
  3877.     return -1;
  3878. }
  3879.  
  3880. #define DIR_BUF 4096
  3881.  
  3882. /*
  3883.  *----------------------------------------------------------------------
  3884.  *
  3885.  * Fs_GetdirInt --
  3886.  *
  3887.  *    This is an internal routine to get some directory entries.
  3888.  *    It does the byteswapping on the buffer.
  3889.  *    A partial record won't be byteswapped.
  3890.  *    It will read the requested number of bytes if they exist.
  3891.  *    The file pointer will point to the end of the data read.
  3892.  *
  3893.  * Results:
  3894.  *    Returns number of bytes read if successful.
  3895.  *    Returns -1 if error.
  3896.  *
  3897.  * Side effects:
  3898.  *    Reads from the file.
  3899.  *    Puts return value in variables.
  3900.  *
  3901.  *----------------------------------------------------------------------
  3902.  */
  3903. /*ARGSUSED*/
  3904. static int
  3905. Fs_GetdirInt(fd, nbytes, buf, off)
  3906.     int            fd;
  3907.     int            nbytes;    /* Length of user buffer. */
  3908.     Address        buf;    /* Kernel space buffer for data. */
  3909.     long        *off;    /* File offset at start */
  3910. {
  3911.     ReturnStatus     status;    /* result returned by Fs_Read */
  3912.     int            i;
  3913.     int            offset;
  3914.     Proc_ControlBlock    *procPtr;
  3915.     Fs_Stream        *streamPtr;
  3916.     int            bytesRead;
  3917.     Fs_Attributes    spriteAttrs;
  3918.     Fslcl_DirEntry    *dirPtr;
  3919.  
  3920.     if (debugFsStubs) {
  3921.     printf("Fs_GetdirInt(%d, %d, %x)\n", fd, nbytes, buf);
  3922.     }
  3923.     if (nbytes < sizeof(struct direct)) {
  3924.     Mach_SetErrno(EINVAL);
  3925.     return -1;
  3926.     }
  3927.     procPtr = Proc_GetEffectiveProc();
  3928.     status = Fs_GetStreamPtr(procPtr, fd, &streamPtr);
  3929.     if (status == SUCCESS) {
  3930.     status = Fs_GetAttrStream(streamPtr, &spriteAttrs);
  3931.     }
  3932.     if (status != SUCCESS) {
  3933.     Mach_SetErrno(EBADF);
  3934.     return -1;
  3935.     }
  3936.     if (spriteAttrs.type != FS_DIRECTORY) {
  3937.     Mach_SetErrno(ENOTDIR);
  3938.     return -1;
  3939.     }
  3940.  
  3941.     offset = streamPtr->offset;
  3942.     *off = offset;
  3943.     bytesRead = nbytes;
  3944.     if (debugFsStubs) {
  3945.     printf("Doing Fs_Read: %x, %x, %x, %x\n", streamPtr, buf, offset,
  3946.         bytesRead);
  3947.     }
  3948.     streamPtr->flags &= ~FS_USER;
  3949.     status = Fs_Read(streamPtr, buf, offset, &bytesRead);
  3950.     streamPtr->flags |= FS_USER;
  3951.     if (status != SUCCESS) {
  3952.     if (debugFsStubs) {
  3953.         printf("Read: status %x\n", status);
  3954.     }
  3955.     Mach_SetErrno(Compat_MapCode(status));
  3956.     return -1;
  3957.     }
  3958.  
  3959.     /*
  3960.      * Check against big-endian/little-endian conflict.
  3961.      * The max record length is 512, which is 02 when byteswapped.
  3962.      * The min record length is 8, which is > 512 when byteswapped.
  3963.      * All other values fall outside the range 8-512 when byteswapped.
  3964.      */
  3965.     dirPtr = (Fslcl_DirEntry *)buf;
  3966.     if (debugFsStubs) {
  3967.     printf("Fs_GetdirInt: recordLength = %d\n", dirPtr->recordLength);
  3968.     }
  3969.     if (dirPtr->recordLength > FSLCL_DIR_BLOCK_SIZE ||
  3970.     dirPtr->recordLength < 2 * (int)sizeof(int)) {
  3971.     if (debugFsStubs) {
  3972.         printf("Fs_GetdirInt: swapping entries\n");
  3973.         printf("Bytes: %x %x %x %x\n", ((int *)buf)[0], ((int *)buf)[1],
  3974.         ((int *)buf)[2], ((int *)buf)[3]);
  3975.     }
  3976.     i = bytesRead;
  3977.     while (i >= (int)(sizeof(u_long)+2*sizeof(u_short))) {
  3978.         union {
  3979.         short    s;
  3980.         char    c[2];
  3981.         } shortIn, shortOut;
  3982.         union {
  3983.         int    i;
  3984.         char    c[4];
  3985.         } intIn, intOut;
  3986.  
  3987.         intIn.i = dirPtr->fileNumber;
  3988.         intOut.c[0] = intIn.c[3];
  3989.         intOut.c[1] = intIn.c[2];
  3990.         intOut.c[2] = intIn.c[1];
  3991.         intOut.c[3] = intIn.c[0];
  3992.         dirPtr->fileNumber = intOut.i;
  3993.  
  3994.         shortIn.s = dirPtr->recordLength;
  3995.         shortOut.c[0] = shortIn.c[1];
  3996.         shortOut.c[1] = shortIn.c[0];
  3997.         dirPtr->recordLength = shortOut.s;
  3998.  
  3999.         shortIn.s = dirPtr->nameLength;
  4000.         shortOut.c[0] = shortIn.c[1];
  4001.         shortOut.c[1] = shortIn.c[0];
  4002.         dirPtr->nameLength = shortOut.s;
  4003.  
  4004.         if (dirPtr->recordLength <= 0) {
  4005.         printf("Fs_GetdirInt: length = %d!!\n", dirPtr->recordLength);
  4006.         return -1;
  4007.         }
  4008.         i -= dirPtr->recordLength;
  4009.         dirPtr = (Fslcl_DirEntry *) ((Address)dirPtr +
  4010.             dirPtr->recordLength);
  4011.     }
  4012.     }
  4013.     return bytesRead;
  4014. }
  4015.  
  4016. /*
  4017.  *----------------------------------------------------------------------
  4018.  *
  4019.  * Fs_GetdentsStub --
  4020.  *
  4021.  *    The stub for the "getdents" Unix system call.
  4022.  *
  4023.  * Results:
  4024.  *    Returns -1 on failure.
  4025.  *
  4026.  * Side effects:
  4027.  *    Side effects associated with the system call.
  4028.  *     
  4029.  *
  4030.  *----------------------------------------------------------------------
  4031.  */
  4032. int
  4033. Fs_GetdentsStub(fd, buf, nbytes)
  4034.     int  fd;
  4035.     char *buf;
  4036.     int nbytes;
  4037. {
  4038.     ReturnStatus     status;
  4039.     int            bytesRead;
  4040.     int            bytesStored, bytesUsed;
  4041.     char        *kBuf;
  4042.     char        *kBuf2;
  4043.     Address        directPtr, directPtr2;
  4044.     long        offset;
  4045.     int            dirsiz;
  4046.  
  4047.     if (debugFsStubs) {
  4048.     printf("Fs_Getdents(%d, %x, %d)\n", fd, buf, nbytes);
  4049.     }
  4050.     assert(sizeof(struct dirent) == sizeof(struct direct)+4);
  4051.  
  4052.     if (nbytes<sizeof(struct dirent)) {
  4053.     Mach_SetErrno(EINVAL);
  4054.     return -1;
  4055.     }
  4056.  
  4057.     if (nbytes>DIR_BUF) {
  4058.     nbytes = DIR_BUF;
  4059.     }
  4060.  
  4061.     kBuf = (char *)malloc(DIR_BUF);
  4062.     kBuf2 = (char *)malloc(DIR_BUF);
  4063.  
  4064.     bytesStored = 0;
  4065.     while (bytesStored==0) {
  4066.     bytesRead = Fs_GetdirInt(fd, nbytes, kBuf, &offset);
  4067.     bytesUsed = 0;
  4068.     if (debugFsStubs) {
  4069.         printf("Fs_Getdirentries got %d bytes from Fs_GetdirInt\n",
  4070.             bytesRead);
  4071.     }
  4072.     if (bytesRead <=0) {
  4073.         free((Address)kBuf);
  4074.         free((Address)kBuf2);
  4075.         return bytesRead;
  4076.     }
  4077.  
  4078.     /*
  4079.      * Scan through the entries converting them to the new format.
  4080.      * directPtr points to the directory we read in.
  4081.      * directPtr2 points to the directory we are creating.
  4082.      * We can take bytesRead bytes from directPtr, and we count these
  4083.      * in bytesUsed.
  4084.      * We can put nbytes bytes into directPtr2, and we count these
  4085.      * in bytesStored.
  4086.      */
  4087.  
  4088.     directPtr = kBuf;
  4089.     directPtr2 = kBuf2;
  4090.  
  4091.     while (bytesUsed+sizeof(u_long)+2*sizeof(u_short) <= bytesRead &&
  4092.         bytesStored < nbytes) {
  4093.         dirsiz = DIRSIZ((struct direct *)directPtr);
  4094.         if (dirsiz > sizeof(struct direct) || ((struct direct *)
  4095.             directPtr)->d_reclen > FSLCL_DIR_BLOCK_SIZE) {
  4096.         printf("Fs_Getdirentries: Directory record too long!\n");
  4097.         printf("dirsiz = %d, reclen = %d\n", dirsiz,
  4098.             ((struct direct *)directPtr)->d_reclen);
  4099.         free((Address)kBuf);
  4100.         free((Address)kBuf2);
  4101.         Mach_SetErrno(EINVAL);
  4102.         return -1;
  4103.         }
  4104.         if (((struct direct *)directPtr)->d_ino != 0) {
  4105.         if (bytesUsed+dirsiz>bytesRead ||
  4106.             bytesStored+dirsiz+sizeof(off_t)>nbytes){
  4107.             break;
  4108.         }
  4109.         bcopy(directPtr, directPtr2+sizeof(off_t), dirsiz);
  4110.         ((struct dirent *)directPtr2)->d_off = offset+bytesUsed;
  4111.         ((struct dirent *)directPtr2)->d_reclen = dirsiz+sizeof(off_t);
  4112.         bytesStored += dirsiz+sizeof(off_t);
  4113.         directPtr2 += dirsiz+sizeof(off_t);
  4114.         }
  4115.         bytesUsed += ((struct direct *)directPtr)->d_reclen;
  4116.         directPtr += ((struct direct *)directPtr)->d_reclen;
  4117.         if (bytesStored > nbytes) {
  4118.         printf("Overflow! %d vs %d, %d vs %d\n", bytesUsed, bytesRead,
  4119.             bytesStored, nbytes);
  4120.         free((Address)kBuf);
  4121.         free((Address)kBuf2);
  4122.         Mach_SetErrno(EINVAL);
  4123.         return -1;
  4124.         }
  4125.     }
  4126.  
  4127.     /*
  4128.      * Set the file pointer.
  4129.      */
  4130.     if (bytesUsed != bytesRead) {
  4131.         if (debugFsStubs) {
  4132.         printf("old offset = %d, read %d, used %d\n",
  4133.             offset, bytesRead, bytesUsed);
  4134.         }
  4135.         status = Fs_LseekStub(fd, offset+bytesUsed, L_SET);
  4136.         if (status < 0) {
  4137.         printf("Lseek to %d failed in getdents!\n", offset+bytesUsed);
  4138.         free((Address)kBuf);
  4139.         free((Address)kBuf2);
  4140.         return -1;
  4141.         }
  4142.     }
  4143.     }
  4144.  
  4145.     /*
  4146.      * Copy out the results.
  4147.      */
  4148.  
  4149.     status = Vm_CopyOut(bytesStored, kBuf2, buf);
  4150.     if (status != SUCCESS) {
  4151.     Mach_SetErrno(EFAULT);
  4152.     free((Address)kBuf);
  4153.     free((Address)kBuf2);
  4154.     return -1;
  4155.     }
  4156.  
  4157.     free((Address)kBuf);
  4158.     free((Address)kBuf2);
  4159.     return bytesStored;
  4160. }
  4161. /*
  4162.  *----------------------------------------------------------------------
  4163.  *
  4164.  * Fs_GetdirentriesStub --
  4165.  *
  4166.  *    The stub for the "getdirentries" Unix system call.
  4167.  *
  4168.  * Results:
  4169.  *    Returns -1 on failure.
  4170.  *
  4171.  * Side effects:
  4172.  *    Side effects associated with the system call.
  4173.  *     
  4174.  *
  4175.  *----------------------------------------------------------------------
  4176.  */
  4177. int 
  4178. Fs_GetdirentriesStub(fd, buf, nbytes, basep)
  4179.     int  fd;
  4180.     char *buf;
  4181.     int nbytes;
  4182.     long *basep;
  4183.  
  4184. {
  4185.     ReturnStatus     status;
  4186.     int            bytesRead;
  4187.     int            bytesStored, bytesUsed;
  4188.     char        *kBuf;
  4189.     char        *kBuf2;
  4190.     Address        directPtr, directPtr2;
  4191.     long        offset;
  4192.     int            dirsiz;
  4193.  
  4194.     if (debugFsStubs) {
  4195.     printf("Fs_Getdirentries(%d, %x, %d, %x)\n", fd, buf, nbytes, basep);
  4196.     }
  4197.  
  4198.     if (nbytes > DIR_BUF) {
  4199.     nbytes = DIR_BUF;
  4200.     }
  4201.  
  4202.     kBuf = (char *)malloc(DIR_BUF);
  4203.     kBuf2 = (char *)malloc(DIR_BUF);
  4204.  
  4205.     bytesStored = 0;
  4206.     while (bytesStored==0) {
  4207.     bytesRead = Fs_GetdirInt(fd, nbytes, kBuf, &offset);
  4208.     bytesUsed = 0;
  4209.     if (debugFsStubs) {
  4210.         printf("Fs_Getdirentries got %d bytes from Fs_GetdirInt\n",
  4211.             bytesRead);
  4212.     }
  4213.     if (bytesRead <=0) {
  4214.         free((Address)kBuf);
  4215.         free((Address)kBuf2);
  4216.         return bytesRead;
  4217.     }
  4218.  
  4219.     /*
  4220.      * Scan through the entries converting them to the new format.
  4221.      * directPtr points to the directory we read in.
  4222.      * directPtr2 points to the directory we are creating.
  4223.      * We can take bytesRead bytes from directPtr, and we count these
  4224.      * in bytesUsed.
  4225.      * We can put nbytes bytes into directPtr2, and we count these
  4226.      * in bytesStored.
  4227.      */
  4228.  
  4229.     directPtr = kBuf;
  4230.     directPtr2 = kBuf2;
  4231.  
  4232.     while (bytesUsed+sizeof(u_long)+2*sizeof(u_short) <= bytesRead &&
  4233.         bytesStored < nbytes) {
  4234.         dirsiz = DIRSIZ((struct direct *)directPtr);
  4235.         if (dirsiz > sizeof(struct direct) || ((struct direct *)
  4236.             directPtr)->d_reclen > FSLCL_DIR_BLOCK_SIZE) {
  4237.         printf("Fs_Getdirentries: Directory record too long!\n");
  4238.         Mach_SetErrno(EINVAL);
  4239.         free((Address)kBuf);
  4240.         free((Address)kBuf2);
  4241.         return -1;
  4242.         }
  4243.         if (((struct direct *)directPtr)->d_ino != 0) {
  4244.         if (bytesUsed+dirsiz>bytesRead || bytesStored+dirsiz>nbytes){
  4245.             break;
  4246.         }
  4247.         bcopy(directPtr, directPtr2, dirsiz);
  4248.         ((struct direct *)directPtr2)->d_reclen = dirsiz;
  4249.         bytesStored += dirsiz;
  4250.         directPtr2 += dirsiz;
  4251.         }
  4252.         bytesUsed += ((struct direct *)directPtr)->d_reclen;
  4253.         directPtr += ((struct direct *)directPtr)->d_reclen;
  4254.         if (bytesStored > nbytes) {
  4255.         printf("Overflow! %d vs %d, %d vs %d\n", bytesUsed, bytesRead,
  4256.             bytesStored, nbytes);
  4257.         Mach_SetErrno(EINVAL);
  4258.         free((Address)kBuf);
  4259.         free((Address)kBuf2);
  4260.         return -1;
  4261.         }
  4262.     }
  4263.  
  4264.     /*
  4265.      * Set the file pointer.
  4266.      */
  4267.     if (bytesUsed != bytesRead) {
  4268.         status = Fs_LseekStub(fd, offset+bytesUsed, L_SET);
  4269.         if (status < 0) {
  4270.         printf("Lseek to %d failed in getdents!\n", offset+bytesUsed);
  4271.         free((Address)kBuf);
  4272.         free((Address)kBuf2);
  4273.         return -1;
  4274.         }
  4275.     }
  4276.     }
  4277.  
  4278.     /*
  4279.      * Copy out the results.
  4280.      */
  4281.  
  4282.     status = Vm_CopyOut(sizeof(long), (Address)&offset, (Address)basep);
  4283.     if (status != SUCCESS) {
  4284.     Mach_SetErrno(EFAULT);
  4285.     free((Address)kBuf);
  4286.     free((Address)kBuf2);
  4287.     return -1;
  4288.     }
  4289.     status = Vm_CopyOut(bytesStored, kBuf2, buf);
  4290.     if (status != SUCCESS) {
  4291.     Mach_SetErrno(EFAULT);
  4292.     free((Address)kBuf);
  4293.     free((Address)kBuf2);
  4294.     return -1;
  4295.     }
  4296.  
  4297.     free((Address)kBuf);
  4298.     free((Address)kBuf2);
  4299.     return bytesStored;
  4300. }
  4301.